1 /*
2 * IceBreaker
3 * Copyright (c) 2000-2002 Matthew Miller <mattdm@mattdm.org>
4 *   http://www.mattdm.org/
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21 
22 
23 #include <SDL.h>
24 #include "icebreaker.h"
25 #include "globals.h"
26 #include "line.h"
27 #include "laundry.h"
28 #include "grid.h"
29 #include "themes.h"
30 
createline(int linenum)31 Line createline(int linenum)
32 {
33 	static Line l;
34 
35 	memset(&l, 0, sizeof(l));
36 	switch (linenum)
37 	{
38 		case 1:
39 			l.id='1';
40 			l.colorpointer=&(color.line1);
41 		break;
42 		case 2:
43 			l.id='2';
44 			l.colorpointer=&(color.line2);
45 		break;
46 		default:
47 			l.id='L';
48 			l.colorpointer=&(color.background);
49 		break;
50 	}
51 
52 	l.on=false;
53 	l.dir=UP;
54 	l.geom.x=0;
55 	l.geom.y=0;
56 	l.geom.w=BLOCKWIDTH;
57 	l.geom.h=BLOCKHEIGHT;
58 	l.mark=l.geom;
59 	l.dead=false;
60 	l.speedslower=false;
61 	l.stuckcount=0;
62 	return(l);
63 }
64 
startline(Line * l,LineDir d,int x,int y)65 void startline(Line * l, LineDir d, int x, int y)
66 {
67 	l->on=true;
68 	l->dir=d;
69 	l->stuckcount=0;
70 
71 	switch (d)
72 	{
73 		case UP:
74 			l->geom.w=BLOCKWIDTH;
75 			l->geom.h=1;
76 			l->geom.x=x;
77 			l->geom.y=y-1;
78 		break;
79 		case DOWN:
80 			l->geom.w=BLOCKWIDTH;
81 			l->geom.h=1;
82 			l->geom.x=x;
83 			l->geom.y=y;
84 		break;
85 		case LEFT:
86 			l->geom.w=1;
87 			l->geom.h=BLOCKHEIGHT;
88 			l->geom.x=x-1;
89 			l->geom.y=y;
90 		break;
91 		case RIGHT:
92 			l->geom.w=1;
93 			l->geom.h=BLOCKHEIGHT;
94 			l->geom.x=x;
95 			l->geom.y=y;
96 		break;
97 	}
98 	l->mark=l->geom;
99 }
100 
101 
moveline(Line * l)102 int moveline(Line * l)
103 {
104 	int finish=false;
105 	char check1;
106 	char check2;
107 
108 	markgrid(l->mark.x,l->mark.y,l->mark.w,l->mark.h,l->id);
109 	SDL_FillRect(screen,&(l->mark),*(l->colorpointer));
110 	soil(l->mark);
111 
112 	switch (l->dir)
113 	{
114 		case UP:
115 			check1=grid[l->geom.x][l->geom.y-1];
116 			check2=grid[l->geom.x+BLOCKWIDTH-1][l->geom.y-1];
117 		break;
118 		case DOWN:
119 			check1=grid[l->geom.x][l->geom.y+l->geom.h];
120 			check2=grid[l->geom.x+BLOCKWIDTH-1][l->geom.y+l->geom.h];
121 		break;
122 		case LEFT:
123 			check1=grid[l->geom.x-1][l->geom.y];
124 			check2=grid[l->geom.x-1][l->geom.y+BLOCKHEIGHT-1];
125 		break;
126 		case RIGHT:
127 			check1=grid[l->geom.x+l->geom.w][l->geom.y];
128 			check2=grid[l->geom.x+l->geom.w][l->geom.y+BLOCKHEIGHT-1];
129 		break;
130 		default: // this will never happen. really.
131 			fprintf(stderr,"Line has no direction. That shouldn't have happened.\n");
132 			check1='!';
133 			check2='!';
134 		break;
135 	}
136 
137 
138 	if (check1 == ' ' && check2 == ' ')
139 	{ // next space is empty
140 		switch (l->dir)
141 		{
142 			case UP:
143 				l->geom.y--;
144 				l->geom.h++;
145 				l->mark.y--;
146 				l->mark.h=1;
147 			break;
148 			case DOWN:
149 				l->geom.h++; // increase length of line -- top stays same
150 				l->mark.y+=l->mark.h;
151 				l->mark.h=1;
152 			break;
153 			case LEFT:
154 				l->geom.x--;
155 				l->geom.w++;
156 				l->mark.x--;
157 				l->mark.w=1;
158 			break;
159 			case RIGHT:
160 				l->geom.w++; // increase width of line -- left side stays same
161 				l->mark.x+=l->mark.w;
162 				l->mark.w=1;
163 			break;
164 		}
165 	}
166 	else if (check1 == '*' || check2 == '*')
167 	{ // hit a penguin. kills line.
168 		l->dead=true;
169 	}
170 	else if (check1 == '1' || check2 == '1' || check1 == '2' || check2 == '2')
171 	{
172 		if (l->stuckcount>LINEMAXSTUCK)
173 		{
174 			// FIX -- should play sound when this happens, to
175 			// let users know that this isn't a mistake.
176 			finish=true;
177 		}
178 		else
179 		{
180 			l->stuckcount++;
181 
182 			// FIX: kludge-o-rama!!
183 			// this could work around the irritating thing where
184 			// a line gets started 'on top' of another line. but it
185 			// is totally repairing the symptom, not the bug. *sigh*
186 			//if (l->geom.w==1 || l->geom.h==1) finish=true;
187 		}
188 	}
189 	else
190 	{ // hit something else
191 		finish=true;
192 	}
193 
194 	if (finish)
195 	{
196 		markgrid(l->mark.x,l->mark.y,l->mark.w,l->mark.h,l->id);
197 		SDL_FillRect(screen,&(l->mark),*(l->colorpointer));
198 		soil(l->mark);
199 		finishline(l);
200 		return(1);
201 	}
202 
203 	return(0);
204 }
205 
finishline(Line * l)206 void finishline(Line * l)
207 {
208 	int i;
209 	int quick1=false;
210 	int quick2=false;
211 
212 	l->on=false;
213 
214 	//printwholegrid();
215 
216 	switch (l->dir)
217   	{
218   		case DOWN:
219   		// falls through.
220   		case UP:
221   			markgrid(l->geom.x,l->geom.y,l->geom.w,l->geom.h,'|');
222   			SDL_FillRect(screen,&l->geom,color.background);
223   			soil(l->geom);
224 
225   			// scan along edges to quickly determine if this
226   			// is going to be complicated.
227   			quick1=true; quick2=true;
228   			for (i=l->geom.y+BLOCKHEIGHT/2;i<l->geom.y+l->geom.h;i++)
229   			{
230   				if (grid[l->geom.x-1][i] != ' ' && grid[l->geom.x-1][i] != '*') quick1=false;
231   				if (grid[l->geom.x+BLOCKWIDTH][i] != ' ' && grid[l->geom.x+BLOCKWIDTH][i] != '*') quick2=false;
232   			}
233 
234   			//printf("Quick %d %d\n",quick1,quick2);
235 
236   			checkempty(l->geom.x-BLOCKWIDTH/2,l->geom.y+BLOCKHEIGHT/2);
237   			checkempty(l->geom.x+BLOCKWIDTH+BLOCKWIDTH/2/2,l->geom.y+BLOCKHEIGHT/2);
238 
239   			if (!quick1)
240   				for (i=l->geom.y+BLOCKHEIGHT/2+BLOCKHEIGHT;i<l->geom.y+l->geom.h;i+=BLOCKHEIGHT)
241   					checkempty(l->geom.x-BLOCKWIDTH/2,i);
242   			if (!quick2)
243   				for (i=l->geom.y+BLOCKHEIGHT/2+BLOCKHEIGHT;i<l->geom.y+l->geom.h;i+=BLOCKHEIGHT)
244   					checkempty(l->geom.x+BLOCKWIDTH+BLOCKWIDTH/2,i);
245   		break;
246   		case RIGHT:
247   		// falls through
248   		case LEFT:
249   			markgrid(l->geom.x,l->geom.y,l->geom.w,l->geom.h,'-');
250   			SDL_FillRect(screen,&l->geom,color.background);
251   			soil(l->geom);
252 
253   			// scan along edges to quickly determine if this
254   			// is going to be complicated.
255   			quick1=true; quick2=true;
256   			for (i=l->geom.x+BLOCKWIDTH/2;i<l->geom.x+l->geom.w;i++)
257   			{
258   				if (grid[i][l->geom.y-1] != ' ' && grid[i][l->geom.y-1] != '*') quick1=false;
259   				if (grid[i][l->geom.y+BLOCKHEIGHT] != ' ' && grid[i][l->geom.y+BLOCKHEIGHT] != '*') quick2=false;
260   			}
261 
262   			//printf("Quick %d %d\n",quick1,quick2);
263 
264 	  		checkempty(l->geom.x+BLOCKWIDTH/2,l->geom.y-BLOCKHEIGHT/2);
265 	  		checkempty(l->geom.x+BLOCKWIDTH/2,l->geom.y+BLOCKHEIGHT+BLOCKHEIGHT/2);
266 
267 	  		if (!quick1)
268 	  			for (i=l->geom.x+BLOCKWIDTH/2+BLOCKWIDTH;i<l->geom.x+l->geom.w;i+=BLOCKWIDTH)
269 		  			checkempty(i,l->geom.y-BLOCKHEIGHT/2);
270 
271 	  		if (!quick2)
272 	  			for (i=l->geom.x+BLOCKWIDTH/2+BLOCKWIDTH;i<l->geom.x+l->geom.w;i+=BLOCKWIDTH)
273 		  			checkempty(i,l->geom.y+BLOCKHEIGHT+BLOCKHEIGHT/2);
274 
275 		break;
276 	}
277 
278 }
279 
280 
killline(Line * l)281 void killline(Line * l)
282 {
283 	l->on=false;
284 	l->dead=false;
285 
286 	switch (l->dir)
287   	{
288   		case DOWN:
289 		// falls through.
290   		case UP:
291   			markgrid(l->geom.x,l->geom.y,l->geom.w,l->geom.h,' ');
292   			// FIXORAMA
293   			SDL_BlitSurface(gridsave,&l->geom, screen, &l->geom);
294   			soil(l->geom);
295   		break;
296   		case RIGHT:
297   		// falls through
298   		case LEFT:
299   			markgrid(l->geom.x,l->geom.y,l->geom.w,l->geom.h,' ');
300   			// FIXORAMA
301   			SDL_BlitSurface(gridsave,&l->geom, screen, &l->geom);
302   			soil(l->geom);
303 	  	break;
304 	}
305 }
306