1 /* Pipepanic - a game.
2 Copyright (C) 2006 TheGreenKnight <thegreenknight1500@hotmail.com>
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. */
17 
18 /* Includes */
19 #include <SDL/SDL_main.h>
20 #include <SDL/SDL.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <time.h>
26 #include "main.h"
27 
28 /* Variable declarations */
29 int xres = 640;
30 int yres = 480;
31 int tilew = 48;
32 int tileh = 48;
33 int digitw = 30;
34 int digith = 48;
35 int asciiw = 30;
36 int asciih = 30;
37 int sdl_fullscreen = FALSE;
38 int fpstest = 0;
39 SDL_Surface *screen;
40 SDL_Surface *digits;
41 SDL_Surface *tiles;
42 SDL_Surface *ascii;
43 SDL_Surface *temp;
44 SDL_Event event;
45 char *current_dir;
46 char *user_home_dir;
47 int quit = 0;
48 int game_mode = GAMEON;
49 int previous_game_mode = 0;
50 int redraw = REDRAWALL;
51 int highscoretable[5] = {0, 0, 0, 0, 0};
52 int highscoreboard[5][BOARDH * BOARDW];
53 int score = 0;
54 int disablescoring = FALSE;
55 int gametime = GAMETIME;
56 Uint32 gametime_ticks = 0;
57 Uint32 fps_ticks = 0;
58 Uint32 cleardeadpipes_ticks = 0;
59 Uint32 fillpipes_ticks = 0;
60 Uint32 flashhighscore_ticks = 0;
61 long int frames = 0;
62 int drawpipearray[BOARDH * BOARDW + 1][3];	/* y|x|filled-or-empty */
63 int previewarray[PREVIEWARRAYSIZE];
64 int pipearray[PIPEARRAYSIZE];
65 int pipearraypointer = PIPEARRAYSIZE;
66 int boardarray[BOARDH][BOARDW];
67 int deadpipesarray[BOARDH][BOARDW];
68 int cleardeadpipesy = 0, cleardeadpipesx = 0;
69 int fillpipespasscounter = FILLEDCOUNTERBASE;
70 int flashhighscorestate = FALSE;
71 int helppage = 0;
72 /*						  ! "  #  $  %  &  ' ( ) *  + , - . / 0  1  2  3  4  5  6  7  8  9  : ; <  =  >  ?  @  A  B  C  D  E  F  G  H  I J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  [ \ ] ^  _  ' a  b  c  d  e  f g  h  i j k  l m  n  o  p  q  r s  t u  v  w  x  y  z  { | } ~ */
73 int asciiwidths[100] = {7,5,10,11,11,18,15,6,6,6,9,11,5,8,5,7,13,10,12,13,14,13,13,13,13,13,5,5,11,11,11,12,15,15,14,13,14,13,12,15,14,6,12,15,12,16,14,16,13,16,14,14,14,14,15,19,13,13,14,8,6,8,11,10,6,13,12,13,12,13,8,13,11,6,6,12,6,17,11,13,12,12,8,12,9,11,12,18,13,12,11,8,4,8,11};
74 
75 /* Function prototypes */
76 int get_machine_id(void);
77 void clear_screen(void);
78 int load_bitmaps(void);
79 void draw_game(void);
80 void draw_digits(int value, int digitcount, int xpos, int ypos);
81 void initialise_new_game(void);
82 void manage_user_input(void);
83 int getnextpipepiece(void);
84 void fillpipearray(void);
85 int fillpipearraypieces(int pipepiece, int frequency, int nextpointer);
86 void get_pipe_src_xy(int pipeid, int *x, int *y, int drawpipefilled);
87 void createdeadpipesarray(void);
88 void cleardeadpipes(void);
89 void fillpipes(void);
90 void read_rc_file(void);
91 void save_rc_file(void);
92 void draw_ascii(char *text, int xpos, int ypos);
93 void manage_help_input(int input);
94 
95 /***************************************************************************
96  * Main                                                                    *
97  ***************************************************************************/
98 
99 #ifdef __cplusplus
100 extern "C"
101 #endif
main(int argc,char * argv[])102 int main(int argc, char *argv[]) {
103 	int count, count2;
104 
105 	/* Initialise the highscoreboard array because there may not yet
106 	   be a saved highscore[board]/rc file */
107 	for (count = 0; count < 5; count++) {
108 		for (count2 = 0; count2 < BOARDH * BOARDW; count2++) {
109 			highscoreboard[count][count2] = NULLPIPEVAL;
110 		}
111 	}
112 
113 	srand((unsigned) time(NULL));	/* Seed C's random number generator */
114 
115 	current_dir = getenv("PWD");
116 	user_home_dir = getenv("HOME");
117 
118 	#ifdef DEBUG
119 	printf("PWD=%s\n", current_dir);
120 	printf("HOME=%s\n", user_home_dir);
121 	#endif
122 
123 	if (get_machine_id()) return 1;	/* This sets up the screen and tile sizes. */
124 
125 	#ifdef DEBUG
126 	printf("Reading resource file -> ");
127 	#endif
128 	read_rc_file();	/* This gets the saved highscore[s] */
129 
130 	/* Process any command line arguments. These will override any found in the resource file. */
131 	if (argc > 1) {
132 		int count;
133 		for (count = argc - 1; count > 0; count--) {
134 			if (!strcmp(argv[count], "--help")) {
135 					/*  1234567890123456789012345678901234567890 <- Formatting for small terminal. */
136 				printf("\nPipepanic version %s\n", VERSION);
137 				printf("Usage: pipepanic [option] [option]...\n");
138 				printf("Options:\n");
139 				printf("  -240x320   Suitable for the SL5X00\n");
140 				printf("  -320x240   Suitable for the SL5X00\n");
141 				printf("  -640x480   Suitable for the C Series\n");
142 				printf("  -480x640   Suitable for the SL6000\n");
143 				printf("  -f         Run the game fullscreen\n");
144 				printf("  -fpstest   Run a 10s fps test and quit\n\n");
145 				return 0;
146 			} else if (!strcmp(argv[count], "-240x320")) {
147 				xres = 240; yres = 320;
148 				tilew = tileh = digith = 24; digitw = 15; asciiw = asciih = 15;
149 			} else if (!strcmp(argv[count], "-320x240")) {
150 				xres = 320; yres = 240;
151 				tilew = tileh = digith = 24; digitw = 15; asciiw = asciih = 15;
152 			} else if (!strcmp(argv[count], "-640x480")) {
153 				xres = 640; yres = 480;
154 				tilew = tileh = digith = 48; digitw = 30; asciiw = asciih = 30;
155 			} else if (!strcmp(argv[count], "-480x640")) {
156 				xres = 480; yres = 640;
157 				tilew = tileh = digith = 48; digitw = 30; asciiw = asciih = 30;
158 			} else if (!strcmp(argv[count], "-fpstest")) {
159 				fpstest = 1;
160 			} else if (!strcmp(argv[count], "-f")) {
161 				sdl_fullscreen = SDL_FULLSCREEN;
162 			} else {
163 				printf("\n'%s' not recognised. Try '--help'.\n\n", argv[count]);
164 				return 0;
165 			}
166 		}
167 	}
168 
169 	/* Initialise SDL */
170 	if(SDL_Init(SDL_INIT_VIDEO)) {
171 		printf("%s: Cannot initialise SDL: %s\n", __func__, SDL_GetError());
172 		return 1;
173 	}
174 
175 	atexit(SDL_Quit);
176 
177 	#ifdef DEBUG
178 	printf("Setting video mode %ix%i\n", xres, yres);
179 	#endif
180 
181 	/* Set SDL video mode */
182 	screen = SDL_SetVideoMode(xres, yres, 16, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_ANYFORMAT | sdl_fullscreen);
183 	if(screen == NULL) {
184 		printf("%s: Cannot initialise screen: %s\n", __func__, SDL_GetError());
185 		exit(1);
186 	}
187 
188 	#ifdef DEBUG
189 	printf ("Loading bitmaps\n");
190 	#endif
191 
192 	if (load_bitmaps()) exit(1);
193 
194 	/* Initialise new game */
195 	initialise_new_game();
196 
197 	/* Main game loop */
198 	while(quit == 0) {
199 		if(game_mode == GAMESHOWHELP) {
200 			/***************************************************************************
201 			 * GAMESHOWHELP                                                            *
202 			 ***************************************************************************/
203 			draw_game();
204 			manage_user_input();
205 		} else if(game_mode == GAMEON) {
206 			/***************************************************************************
207 			 * GAMEON                                                                  *
208 			 ***************************************************************************/
209 	 		/* Check to see if the time needs to be updated */
210 			if (SDL_GetTicks() - gametime_ticks >= 1000) {
211 				redraw = redraw | REDRAWTIMER;
212 				gametime_ticks = SDL_GetTicks();
213 				gametime = gametime - 1;
214 				if (gametime <= 0) {
215 					gametime = 0;
216 					createdeadpipesarray();
217 				}
218 			}
219 			draw_game();
220 			manage_user_input();
221 		} else if(game_mode == GAMECLEARDEADPIPES) {
222 			/***************************************************************************
223 			 * GAMECLEARDEADPIPES                                                      *
224 			 ***************************************************************************/
225 			if (SDL_GetTicks() - cleardeadpipes_ticks >= CLEARDEADPIPESTIMEOUT) {
226 				cleardeadpipes_ticks = SDL_GetTicks();
227 				cleardeadpipes();
228 			}
229 			draw_game();
230 			manage_user_input();
231 		} else if(game_mode == GAMEFILLPIPES) {
232 			/***************************************************************************
233 			 * GAMEFILLPIPES                                                           *
234 			 ***************************************************************************/
235 			if(SDL_GetTicks() - fillpipes_ticks >= FILLPIPESTIMEOUT) {
236 				fillpipes_ticks = SDL_GetTicks();
237 				fillpipes();
238 			}
239 			draw_game();
240 			manage_user_input();
241 		} else if(game_mode == GAMEFLASHHIGHSCORE) {
242 			/***************************************************************************
243 			 * GAMEFLASHHIGHSCORE                                                      *
244 			 ***************************************************************************/
245 			if (SDL_GetTicks() - flashhighscore_ticks >= FLASHHIGHSCORETIMEOUT) {
246 				flashhighscore_ticks = SDL_GetTicks();
247 				redraw = redraw | REDRAWHIGHSCORE;
248 				if (flashhighscorestate) {
249 					flashhighscorestate = FALSE;
250 				} else {
251 					flashhighscorestate = TRUE;
252 				}
253 			}
254 			draw_game();
255 			manage_user_input();
256 		} else if(game_mode == GAMEOVER) {
257 			/***************************************************************************
258 			 * GAMEOVER                                                                *
259 			 ***************************************************************************/
260 			draw_game();
261 			manage_user_input();
262 		}
263 		if (!fpstest) SDL_Delay(9);	/* Reduce CPU load to almost nothing */
264 	}
265 
266 	/* Shutdown all subsystems */
267 	SDL_Quit();
268 
269 	/* Show fps if requested */
270 	if (fpstest) printf("fps=%li\n", frames / 10);
271 
272 	return 0;
273 }
274 
275 /***************************************************************************
276  * Get Machine ID                                                          *
277  ***************************************************************************/
278 /* This looks for the file /proc/deviceinfo/product which exists on the
279    Zaurus and not the PC and then sets the screen resolution accordingly.
280    On exit: returns 1 if file found but product unknown else 0. */
281 
get_machine_id(void)282 int get_machine_id(void) {
283 	char buffer[256];
284 	int returnval = 0;
285 	FILE *file = fopen( "/proc/deviceinfo/product", "r" );
286 
287 	if (file) {
288 		fgets(buffer, 255, file);
289 		#ifdef DEBUG
290 		printf("product=%s\n", buffer);
291 		#endif
292 		if (!strncmp(buffer, "SL-5", 4)) {
293 			xres = 240; yres = 320;
294 			tilew = tileh = digith = 24; digitw = 15; asciiw = asciih = 15;
295 		} else if (!strncmp(buffer, "SL-C", 4)) {
296 			xres = 640; yres = 480;
297 			tilew = tileh = digith = 48; digitw = 30; asciiw = asciih = 30;
298 		} else if (!strncmp(buffer, "SL-6", 4)) {
299 			xres = 480; yres = 640;
300 			tilew = tileh = digith = 48; digitw = 30; asciiw = asciih = 30;
301 		} else {
302 			printf("product=%s\n", buffer);
303 			printf("Unknown Zaurus model! Please email me the product shown above.\n");
304 			returnval = 1;
305 		}
306 		fclose (file);
307 	}
308 	return returnval;
309 }
310 
311 /***************************************************************************
312  * Clear Screen                                                            *
313  ***************************************************************************/
314 /* This simply sets the screen to black. */
315 
clear_screen(void)316 void clear_screen(void) {
317 	SDL_Rect dest;
318 
319 	dest.x = dest.y = 0; dest.w = screen->w; dest.h = screen->h;
320 	SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, BLACK));
321 }
322 
323 /***************************************************************************
324  * Load Bitmaps                                                            *
325  ***************************************************************************/
326 /* This locates and loads the relevant bitmap images. They are converted to
327    the display format for optimisation. Also RLE is enabled for the colorkey
328    which makes probably the biggest difference in frame rate I have found yet.
329    On exit: returns 1 if an error occured else 0. */
330 
load_bitmaps(void)331 int load_bitmaps(void) {
332 	if (xres == 320 || xres == 240) {
333 		/* First check current dir. */
334 		if((temp = SDL_LoadBMP(DIGITS24BMP)) == NULL) {
335 			/* Now check DATADIR. */
336 			if((temp = SDL_LoadBMP(DATADIR DIGITS24BMP)) == NULL) {
337 				printf("%s: Cannot find file %s\n", __func__, DIGITS24BMP);
338 				return 1;
339 			}
340 		}
341 		if((digits = SDL_DisplayFormat(temp)) == NULL) {
342 			printf("%s: SDL_DisplayFormat error: %s\n", __func__, SDL_GetError());
343 			return 1;
344 		}
345 		SDL_FreeSurface(temp);
346 
347 		/* First check current dir. */
348 		if((temp = SDL_LoadBMP(TILES24BMP)) == NULL) {
349 			/* Now check DATADIR. */
350 			if((temp = SDL_LoadBMP(DATADIR TILES24BMP)) == NULL) {
351 				printf("%s: Cannot find file %s\n", __func__, TILES24BMP);
352 				return 1;
353 			}
354 		}
355 		SDL_SetColorKey(temp, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(temp->format, MAGENTA));
356 		if((tiles = SDL_DisplayFormat(temp)) == NULL) {
357 			printf("%s: SDL_DisplayFormat error: %s\n", __func__, SDL_GetError());
358 			return 1;
359 		}
360 		SDL_FreeSurface(temp);
361 
362 		/* First check current dir. */
363 		if((temp = SDL_LoadBMP(ASCII15BMP)) == NULL) {
364 			/* Now check DATADIR. */
365 			if((temp = SDL_LoadBMP(DATADIR ASCII15BMP)) == NULL) {
366 				printf("%s: Cannot find file %s\n", __func__, ASCII15BMP);
367 				return 1;
368 			}
369 		}
370 		SDL_SetColorKey(temp, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(temp->format, WHITE));
371 		if((ascii = SDL_DisplayFormat(temp)) == NULL) {
372 			printf("%s: SDL_DisplayFormat error: %s\n", __func__, SDL_GetError());
373 			return 1;
374 		}
375 		SDL_FreeSurface(temp);
376 
377 	} else if (xres == 640 || xres == 480) {
378 		/* First check current dir. */
379 		if((temp = SDL_LoadBMP(DIGITS48BMP)) == NULL) {
380 			/* Now check DATADIR. */
381 			if((temp = SDL_LoadBMP(DATADIR DIGITS48BMP)) == NULL) {
382 				printf("%s: Cannot find file %s\n", __func__, DIGITS48BMP);
383 				return 1;
384 			}
385 		}
386 		if((digits = SDL_DisplayFormat(temp)) == NULL) {
387 			printf("%s: SDL_DisplayFormat error: %s\n", __func__, SDL_GetError());
388 			return 1;
389 		}
390 		SDL_FreeSurface(temp);
391 
392 		/* First check current dir. */
393 		if((temp = SDL_LoadBMP(TILES48BMP)) == NULL) {
394 			/* Now check DATADIR. */
395 			if((temp = SDL_LoadBMP(DATADIR TILES48BMP)) == NULL) {
396 				printf("%s: Cannot find file %s\n", __func__, TILES48BMP);
397 				return 1;
398 			}
399 		}
400 		SDL_SetColorKey(temp, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(temp->format, MAGENTA));
401 		if((tiles = SDL_DisplayFormat(temp)) == NULL) {
402 			printf("%s: SDL_DisplayFormat error: %s\n", __func__, SDL_GetError());
403 			return 1;
404 		}
405 		SDL_FreeSurface(temp);
406 
407 			/* First check current dir. */
408 		if((temp = SDL_LoadBMP(ASCII30BMP)) == NULL) {
409 			/* Now check DATADIR. */
410 			if((temp = SDL_LoadBMP(DATADIR ASCII30BMP)) == NULL) {
411 				printf("%s: Cannot find file %s\n", __func__, ASCII30BMP);
412 				return 1;
413 			}
414 		}
415 		SDL_SetColorKey(temp, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(temp->format, WHITE));
416 		if((ascii = SDL_DisplayFormat(temp)) == NULL) {
417 			printf("%s: SDL_DisplayFormat error: %s\n", __func__, SDL_GetError());
418 			return 1;
419 		}
420 		SDL_FreeSurface(temp);
421 	}
422 
423 	return 0;
424 }
425 
426 /***************************************************************************
427  * Draw Game                                                               *
428  ***************************************************************************/
429 /* This draws the game. Either it draws all of it or just parts of it. */
430 
draw_game(void)431 void draw_game(void) {
432 	SDL_Rect src, dest;
433 	int row, column, x, y;
434 
435 	if (fpstest) redraw = REDRAWALL;
436 
437 	if ((redraw & REDRAWBOARD) == REDRAWBOARD) {
438 		/* Paint the whole screen yellow. */
439 		dest.x = dest.y = 0; dest.w = screen->w; dest.h = screen->h;
440 		SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, YELLOW));
441 
442 		/* Draw all the game board background tiles. */
443 		src.x = 4 * tilew; src.y = 6 * tileh;
444 		src.w = tilew; src.h = tileh;
445 		dest.y = 0; if (xres == 240 || xres == 480) dest.y = 2 * tileh;
446 		dest.w = tilew; dest.h = tileh;
447 		for (row = 0; row < BOARDH; row++) {
448 			dest.x = xres -  BOARDW * tilew;
449 			for (column = 0; column < BOARDW; column++) {
450 				if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
451 					printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
452 				dest.x = dest.x + tilew;
453 			}
454 			dest.y = dest.y + tileh;
455 		}
456 
457 		/* Draw all the text. */
458 		/* High Score. */
459 		src.x = 0 * tilew; src.y = 8 * tileh;
460 		src.w = 3 * tilew; src.h = tileh;
461 		dest.x = dest.y = 0; if (xres == 240 || xres == 480) dest.x = 3.7 * tilew;
462 		dest.w = 3 * tilew; dest.h = tileh;
463 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
464 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
465 
466 		/* Score. */
467 		src.x = 3 * tilew; src.y = 8 * tileh;
468 		src.w = 2 * tilew; src.h = tileh;
469 		dest.x = 0; dest.y = 2 * tileh; if (xres == 240 || xres == 480) dest.y = 0;
470 		dest.w = 2 * tilew; dest.h = tileh;
471 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
472 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
473 
474 		/* Time (s). */
475 		src.x = 0 * tilew; src.y = 9 * tileh;
476 		src.w = 3 * tilew; src.h = tileh;
477 		dest.x = 0; if (xres == 240 || xres == 480) dest.x = 7.6 * tilew;
478 		dest.y = 4 * tileh; if (xres == 240 || xres == 480) dest.y = 0;
479 		dest.w = 3 * tilew; dest.h = tileh;
480 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
481 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
482 
483 		/* Fill. */
484 		src.x = 3 * tilew; src.y = 10 * tileh;
485 		src.w = tilew; src.h = tileh;
486 		dest.x = 0; if (xres == 240 || xres == 480) dest.x = 4 * tilew;
487 		dest.y = 7 * tileh; if (xres == 240 || xres == 480) dest.y = 12.18 * tileh;
488 		dest.w = tilew; dest.h = tileh;
489 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
490 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
491 
492 		/* Help. */
493 		src.x = 3 * tilew; src.y = 9 * tileh;
494 		src.w = 2 * tilew; src.h = tileh;
495 		dest.x = 0; if (xres == 240 || xres == 480) dest.x = 5.25 * tilew;
496 		dest.y = 8 * tileh; if (xres == 240 || xres == 480) dest.y = 12.18 * tileh;
497 		dest.w = 3 * tilew; dest.h = tileh;
498 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
499 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
500 
501 		/* New Game. */
502 		src.x = 0 * tilew; src.y = 10 * tileh;
503 		src.w = 3 * tilew; src.h = tileh;
504 		dest.x = 0; if (xres == 240 || xres == 480) dest.x = 6.9 * tilew;
505 		dest.y = 9 * tileh; if (xres == 240 || xres == 480) dest.y = 12.18 * tileh;
506 		dest.w = 3 * tilew; dest.h = tileh;
507 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
508 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
509 	}
510 
511 	if ((redraw & REDRAWALLPIPES) == REDRAWALLPIPES) {
512 		/* Draw any pipes found in the board array.
513 		   NOTE that this doesn't draw the background tile first.
514 		   This is done in REDRAWBOARD above. */
515 		src.w = tilew; src.h = tileh;
516 		dest.y = 0; if (xres == 240 || xres == 480) dest.y = 2 * tileh;
517 		dest.w = tilew; dest.h = tileh;
518 		for (row = 0; row < BOARDH; row++) {
519 			dest.x = xres -  BOARDW * tilew;
520 			for (column = 0; column < BOARDW; column++) {
521 				if (boardarray[row][column] != NULLPIPEVAL) {
522 					get_pipe_src_xy(boardarray[row][column], &x, &y, FALSE);
523 					src.x = x; src.y = y;
524 					if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
525 						printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
526 				}
527 				dest.x = dest.x + tilew;
528 			}
529 			dest.y = dest.y + tileh;
530 		}
531 	}
532 
533 	if ((redraw & REDRAWHIGHSCORE) == REDRAWHIGHSCORE) {
534 		/* The top high score */
535 		/* If flashhighscorestate is TRUE then no score is shown
536 		   (it is blanked out with the background colour). */
537 		dest.x = 0.15 * tilew; if (xres == 240 || xres == 480) dest.x = 4 * tilew;
538 		dest.y = 0.9 * tileh;
539 		if (flashhighscorestate) {
540 			dest.w = 5 * digitw; dest.h = digith;
541 			SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, YELLOW));
542 		} else {
543 			draw_digits(highscoretable[0], 4, dest.x, dest.y);
544 		}
545 	}
546 
547 	if ((redraw & REDRAWTIMER) == REDRAWTIMER) {
548 		/* The time */
549 		dest.x = 0.15 * tilew; if (xres == 240 || xres == 480) dest.x = 8 * tilew;
550 		dest.y = 4.9 * tileh; if (xres == 240 || xres == 480) dest.y = 0.9 * tileh;
551 		draw_digits(gametime, 3, dest.x, dest.y);
552 	}
553 
554 	if ((redraw & REDRAWSCORE) == REDRAWSCORE) {
555 		/* The score */
556 		dest.x = 0.15 * tilew; if (xres == 240 || xres == 480) dest.x = 0.15 * tilew;
557 		dest.y = 2.9 * tileh; if (xres == 240 || xres == 480) dest.y = 0.9 * tileh;
558 		draw_digits(score, 4, dest.x, dest.y);
559 	}
560 
561 	if ((redraw & REDRAWPREVIEW) == REDRAWPREVIEW) {
562 		/* Draw preview array */
563 		/* Left */
564 		src.x = 1 * tilew; src.y = 7 * tileh;
565 		src.w = tilew; src.h = tileh;
566 		dest.x = 0.09 * tilew; if (xres == 240 || xres == 480) dest.x = 0.09 * tilew;
567 		dest.y = 6 * tileh; if (xres == 240 || xres == 480) dest.y = 12.18 * tileh;
568 		dest.w = tilew; dest.h = tileh;
569 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
570 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
571 		get_pipe_src_xy(previewarray[2], &x, &y, FALSE);
572 		src.x = x; src.y = y;
573 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
574 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
575 
576 		/* Middle */
577 		src.x = 1 * tilew; src.y = 7 * tileh;
578 		src.w = tilew; src.h = tileh;
579 		dest.x = 1.18 * tilew; if (xres == 240 || xres == 480) dest.x = 1.18 * tilew;
580 		dest.y = 6 * tileh; if (xres == 240 || xres == 480) dest.y = 12.18 * tileh;
581 		dest.w = tilew; dest.h = tileh;
582 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
583 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
584 		get_pipe_src_xy(previewarray[1], &x, &y, FALSE);
585 		src.x = x; src.y = y;
586 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
587 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
588 
589 		/* Right */
590 		src.x = 0; src.y = 7 * tileh;
591 		src.w = tilew; src.h = tileh;
592 		dest.x = 2.27 * tilew; if (xres == 240 || xres == 480) dest.x = 2.27 * tilew;
593 		dest.y = 6 * tileh; if (xres == 240 || xres == 480) dest.y = 12.18 * tileh;
594 		dest.w = tilew; dest.h = tileh;
595 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
596 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
597 		get_pipe_src_xy(previewarray[0], &x, &y, FALSE);
598 		src.x = x; src.y = y;
599 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
600 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
601 	}
602 
603 	if ((redraw & REDRAWTILE) == REDRAWTILE) {
604 		/* Draw one or more background tiles within the board.
605 		   The offsets into the board are in the draw pipes array */
606 		row = 0;
607 		while(drawpipearray[row][0] != NULLPIPEVAL) {
608 			src.x = 4 * tilew; src.y = 6 * tileh;
609 			src.w = tilew; src.h = tileh;
610 			dest.x = (xres - BOARDW * tilew) + drawpipearray[row][1] * tilew; if (xres == 240 || xres == 480) dest.x = drawpipearray[row][1] * tilew;
611 			dest.y = drawpipearray[row][0] * tileh; if (xres == 240 || xres == 480) dest.y = drawpipearray[row][0] * tileh + 2 * tileh;
612 			dest.w = tilew; dest.h = tileh;
613 			if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
614 				printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
615 			row++;
616 		}
617 	}
618 
619 	if ((redraw & REDRAWPIPE) == REDRAWPIPE) {
620 		/* Draw one or more pipe pieces within the board.
621 		   The offsets into the board array are in the
622 		   draw pipes array */
623 		row = 0;
624 		while(drawpipearray[row][0] != NULLPIPEVAL) {
625 			get_pipe_src_xy(boardarray[drawpipearray[row][0]][drawpipearray[row][1]], &x, &y, drawpipearray[row][2]);
626 			src.x = x; src.y = y;
627 			src.w = tilew; src.h = tileh;
628 			dest.x = (xres - BOARDW * tilew) + drawpipearray[row][1] * tilew; if (xres == 240 || xres == 480) dest.x = drawpipearray[row][1] * tilew;
629 			dest.y = drawpipearray[row][0] * tileh; if (xres == 240 || xres == 480) dest.y = drawpipearray[row][0] * tileh + 2 * tileh;
630 			dest.w = tilew; dest.h = tileh;
631 			if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
632 				printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
633 			row++;
634 		}
635 	}
636 
637 	if ((redraw & REDRAWHELP) == REDRAWHELP) {
638 		/* Show the help pages */
639 		/* Draw a white box to cover the game board */
640 		dest.x = xres -  BOARDW * tilew;
641 		dest.y = 0; if (xres == 240 || xres == 480) dest.y = 2 * tileh;
642 		dest.w = BOARDW * tilew; dest.h = BOARDH * tileh;
643 		SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, WHITE));
644 		/* Draw the Exit text and the navigation buttons */
645 		if(helppage > 0) {
646 			/* Left arrow */
647 			src.x = 2 * tilew; src.y = 7 * tileh;
648 			src.w = tilew; src.h = tileh;
649 			dest.x = xres - BOARDW * tilew; if (xres == 240 || xres == 480) dest.x = 0;
650 			dest.y = (BOARDH - 1) * tileh; if (xres == 240 || xres == 480) dest.y = (BOARDH - 1) * tileh + 2 * tileh;
651 			dest.w = tilew; dest.h = tileh;
652 			if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
653 				printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
654 		}
655 		if(helppage < HELPPAGES - 1) {
656 			/* Right arrow */
657 			src.x = 4 * tilew; src.y = 10 * tileh;
658 			src.w = tilew; src.h = tileh;
659 			dest.x = xres - tilew;
660 			dest.y = (BOARDH - 1) * tileh; if (xres == 240 || xres == 480) dest.y = (BOARDH - 1) * tileh + 2 * tileh;
661 			dest.w = tilew; dest.h = tileh;
662 			if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
663 				printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
664 		}
665 		/* Exit */
666 		src.x = 3 * tilew; src.y = 7 * tileh;
667 		src.w = 2 * tilew; src.h = tileh;
668 		dest.x = xres - 5.6 * tilew;
669 		dest.y = (BOARDH - 1) * tileh; if (xres == 240 || xres == 480) dest.y = (BOARDH - 1) * tileh + 2 * tileh;
670 		dest.w = 2 * tilew; dest.h = tileh;
671 		if(SDL_BlitSurface(tiles, &src, screen, &dest) < 0)
672 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
673 		/* Draw a black surround */
674 		if(xres == 240 || xres == 480) {
675 			/* Top */
676 			dest.x = xres -  BOARDW * tilew;
677 			dest.y = 2 * tileh;
678 			dest.w = BOARDW * tilew; dest.h = 1;
679 			/* Bottom */
680 			SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, BLACK));
681 			dest.x = xres -  BOARDW * tilew;
682 			dest.y = 2 * tileh + BOARDH * tileh - 1;
683 			dest.w = BOARDW * tilew; dest.h = 1;
684 			SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, BLACK));
685 		} else if (xres == 320 || xres == 640){
686 			/* Left */
687 			dest.x = xres -  BOARDW * tilew;
688 			dest.y = 0;
689 			dest.w = 1; dest.h = BOARDW * tilew;
690 			SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, BLACK));
691 		}
692 
693 		x = xres - (BOARDW - 0.2) * tilew;
694 		y = 0.2 * BOARDH; if (xres == 240 || xres == 480) y = 2.2 * tileh;
695 		if(helppage == 0) {
696 			draw_ascii(HELPPAGE0, x, y);
697 		} else if(helppage == 1) {
698 			draw_ascii(HELPPAGE1, x, y);
699 		} else if(helppage == 2) {
700 			draw_ascii(HELPPAGE2, x, y);
701 		} else if(helppage == 3) {
702 			draw_ascii(HELPPAGE3, x, y);
703 		} else if(helppage == 4) {
704 			draw_ascii(HELPPAGE4, x, y);
705 		} else if(helppage == 5) {
706 			draw_ascii(HELPPAGE5, x, y);
707 		}
708 	}
709 
710 	if (redraw != REDRAWNONE) SDL_Flip(screen);
711 
712 	if (fpstest) {
713 		frames++;
714 		if (SDL_GetTicks() - fps_ticks >= 10000) quit = 1;
715 	}
716 
717 	redraw = REDRAWNONE;
718 }
719 
720 /***************************************************************************
721  * Draw Ascii                                                              *
722  ***************************************************************************/
723 /* This writes ASCII text. Embedded "\n" are translated into newlines.
724    On entry: text = pointer to a (C) null terminated string */
725 
draw_ascii(char * text,int xpos,int ypos)726 void draw_ascii(char *text, int xpos, int ypos) {
727 	SDL_Rect src, dest;
728 	int count = 0, x = xpos, y = ypos;
729 
730 	while(text[count] != 0) {
731 		while(text[count] == '\n') {
732 			x = xpos;
733 			y = y + asciih * 0.8;
734 			count++;
735 		}
736 		src.x = ((text[count] - 32) % 10) * asciiw;
737 		src.y = ((text[count] - 32) / 10) * asciih;
738 		src.w = asciiwidths[text[count] - 32]; if (xres == 320 || xres == 240) src.w = src.w / 2;
739 		src.h = asciih;
740 		dest.x = x; dest.y = y;
741 		dest.w = src.w; dest.h = asciih;
742 		if(SDL_BlitSurface(ascii, &src, screen, &dest) < 0)
743 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
744 		x = x + src.w;
745 		count++;
746 	}
747 }
748 
749 /***************************************************************************
750  * Draw Digits                                                             *
751  ***************************************************************************/
752 /* This writes an integer value. If it is negative the minus sign will be
753    shown at the end of the number.
754    On entry: value = an integer value positive or negative
755              digitcount = number of digits to draw
756              xpos = x position to write the number
757              ypos = y position to write the number */
758 
draw_digits(int value,int digitcount,int xpos,int ypos)759 void draw_digits(int value, int digitcount, int xpos, int ypos) {
760 	SDL_Rect src, dest;
761 	int tempvalue = abs(value);
762 	int count, count2, base;
763 
764 	dest.x = xpos; dest.y = ypos;
765 	dest.w = digitw; dest.h = digith;
766 	src.y = 0;
767 	src.w = digitw; src.h = digith;
768 
769 	for (count = digitcount - 1; count >= 0; count--) {
770 		base = count == 0 ? 1 : 10;
771 		for (count2 = count; count2 > 1; count2--) base = base * 10;
772 
773 		src.x = tempvalue / base * digitw;
774 		if(SDL_BlitSurface(digits, &src, screen, &dest) < 0)
775 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
776 
777 		tempvalue = tempvalue % base;
778 		dest.x = dest.x + digitw;
779 	}
780 
781 	if (value < 0) {
782 		src.x = 10 * digitw;
783 		if(SDL_BlitSurface(digits, &src, screen, &dest) < 0)
784 			printf("%s: BlitSurface error: %s\n", __func__, SDL_GetError());
785 	} else {
786 		SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, YELLOW));
787 	}
788 }
789 
790 /***************************************************************************
791  * Initialise New Game                                                     *
792  ***************************************************************************/
793 /* This sets up the variables necessary to start the game afresh. */
794 
initialise_new_game(void)795 void initialise_new_game(void) {
796 	int rowloop, colloop, count;
797 
798 	game_mode = GAMEON;
799 	redraw = REDRAWALL;
800 	score = 0;
801 	disablescoring = FALSE;
802 	flashhighscorestate = FALSE;
803 	gametime = GAMETIME;
804 	gametime_ticks = SDL_GetTicks();
805 
806 	/* Clear the game board array */
807 	for (rowloop = 0; rowloop < BOARDH; rowloop++) {
808 		for (colloop = 0; colloop < BOARDW; colloop++) {
809 			boardarray[rowloop][colloop] = NULLPIPEVAL;
810 		}
811 	}
812 
813 	/* Setup and initialise preview pieces/array. */
814 	pipearraypointer = PIPEARRAYSIZE;
815 	for (count = 0; count < PREVIEWARRAYSIZE; count++) {
816 		previewarray[count] = getnextpipepiece();
817 	}
818 
819 	/* Place end points and record in game board array. */
820 	boardarray[rand() % BOARDH][0] = 1;	/* yx */
821 	boardarray[rand() % BOARDH][BOARDW - 1] = 0;	/* yx */
822 
823 	drawpipearray[0][0] = NULLPIPEVAL;
824 
825 	if (fpstest) {
826 		fps_ticks = SDL_GetTicks();
827 		gametime = 10;
828 	}
829 }
830 
831 /***************************************************************************
832  * Get Next Pipe Piece                                                     *
833  ***************************************************************************/
834 /* Get next piece from the pipe array, or if at end
835    of array refill it and get piece from start. */
836 
getnextpipepiece(void)837 int getnextpipepiece(void) {
838 	pipearraypointer++;
839 	if (pipearraypointer >= PIPEARRAYSIZE) {
840 		fillpipearray();
841 		pipearraypointer = 0;
842 	}
843 	return pipearray[pipearraypointer];
844 }
845 
846 /***************************************************************************
847  * Fill Pipe Array                                                         *
848  ***************************************************************************/
849 /* This fills the pipe array with a set frequency of pipe pieces. The array
850    is then shuffled. */
851 
fillpipearray(void)852 void fillpipearray(void) {
853 	int nextpointer = 0, count, temp, swap;
854 
855 	/* Fill pipe array with our recommended frequency */
856 	nextpointer = fillpipearraypieces(2, 7, nextpointer);
857 	nextpointer = fillpipearraypieces(3, 7, nextpointer);
858 	nextpointer = fillpipearraypieces(4, 7, nextpointer);
859 	nextpointer = fillpipearraypieces(5, 7, nextpointer);
860 	nextpointer = fillpipearraypieces(6, 5, nextpointer);
861 	nextpointer = fillpipearraypieces(7, 5, nextpointer);
862 	nextpointer = fillpipearraypieces(8, 5, nextpointer);
863 	nextpointer = fillpipearraypieces(9, 5, nextpointer);
864 	nextpointer = fillpipearraypieces(10, 5, nextpointer);
865 	nextpointer = fillpipearraypieces(11, 18, nextpointer);
866 	nextpointer = fillpipearraypieces(12, 18, nextpointer);
867 	nextpointer = fillpipearraypieces(13, 4, nextpointer);
868 	nextpointer = fillpipearraypieces(14, 4, nextpointer);
869 	nextpointer = fillpipearraypieces(15, 4, nextpointer);
870 	nextpointer = fillpipearraypieces(16, 4, nextpointer);
871 
872 	/* Go through the pipe array and shuffle the pieces. This maintains frequency :)
873 	   Fiddle with the above figures to tweek it, but don't forget the array size
874 	   is set as a constant and will need to be adjusted accordingly */
875 	for (count = 0; count < PIPEARRAYSIZE; count++) {
876 		temp = pipearray[count];
877 		swap = rand() % PIPEARRAYSIZE;
878 		pipearray[count] = pipearray[swap];
879 		pipearray[swap] = temp;
880 	}
881 }
882 
883 /***************************************************************************
884  * Fill Pipe Array Pieces                                                  *
885  ***************************************************************************/
886 /* This is called by Fill Pipe Array only. */
887 
fillpipearraypieces(int pipepiece,int frequency,int nextpointer)888 int fillpipearraypieces(int pipepiece, int frequency, int nextpointer) {
889 	while (frequency > 0) {
890 		pipearray[nextpointer] = pipepiece;
891 		nextpointer++;
892 		if (nextpointer >= PIPEARRAYSIZE) nextpointer = 0;
893 		frequency--;
894 	}
895 	return nextpointer;
896 }
897 
898 /***************************************************************************
899  * Get Pipe XY                                                             *
900  ***************************************************************************/
901 /* This translates a number identifying a pipe into x and y coordinates
902    into the tiles surface.
903    On entry: pipeid = 0 to 16, the same order the pipes are within the bmp
904              *x
905              *y
906              drawpipefilled = FALSE for empty or TRUE for filled */
907 
get_pipe_src_xy(int pipeid,int * x,int * y,int drawpipefilled)908 void get_pipe_src_xy(int pipeid, int *x, int *y, int drawpipefilled) {
909 	if (pipeid > 16) {
910 		printf("%s: Invalid pipe: %i\n", __func__, pipeid);
911 	} else {
912 		if (drawpipefilled) pipeid = pipeid + 17;
913 		*x = (pipeid % 5) * tilew;
914 		*y = (pipeid / 5) * tileh;
915 	}
916 }
917 
918 /***************************************************************************
919  * Manage User Input                                                       *
920  ***************************************************************************/
921 /* This manages all user input. */
922 
manage_user_input(void)923 void manage_user_input(void) {
924 	int mbut, mx, my, count;
925 	int column = 0, row = 0;
926 
927 	while(SDL_PollEvent(&event)) {
928 		switch(event.type) {
929 			case SDL_KEYDOWN:
930 				switch(event.key.keysym.sym) {
931 					case SDLK_ESCAPE:	/* Cancel on the Zaurus */
932 						if (!fpstest) {
933 							if(game_mode == GAMESHOWHELP) {
934 								manage_help_input(SDLK_ESCAPE);
935 							} else {
936 								quit = 1;
937 							}
938 						}
939 						break;
940 					case SDLK_LEFT:
941 						if (!fpstest) {
942 							if(game_mode == GAMESHOWHELP) {
943 								manage_help_input(SDLK_LEFT);
944 							}
945 						}
946 						break;
947 					case SDLK_RIGHT:
948 						if (!fpstest) {
949 							if(game_mode == GAMESHOWHELP) {
950 								manage_help_input(SDLK_RIGHT);
951 							}
952 						}
953 						break;
954 					default:
955 						break;
956 				}
957 				break;
958 			case SDL_QUIT:
959 				if (!fpstest) {
960 					quit = 1;
961 				}
962 				break;
963 			case SDL_MOUSEBUTTONDOWN:
964 				if (!fpstest) {
965 					mbut = SDL_GetMouseState(&mx, &my);
966 
967 					#ifdef DEBUG
968 					printf("mbut=%i mx=%i my=%i\n", mbut, mx, my);
969 					#endif
970 
971 					switch(mbut) {
972 						case SDL_BUTTON_LEFT:
973 							/* Process game board clicks */
974 							if (game_mode == GAMEON) {
975 								if (((xres == 320 || xres == 640) && (mx >= xres - BOARDW * tilew) && (mx < xres) && (my >= 0) && (my < yres)) || ((xres == 240 || xres == 480) && (mx >= 0) && (mx < xres) && (my >= 2 * tileh) && (my < 12 * tileh))) {
976 									/* Convert the mouse coordinates to offsets into the board array */
977 									if (xres == 320 || xres == 640) {
978 										column = (mx - (xres - BOARDW * tilew)) / tilew;
979 										row = my / tileh;
980 									} else if (xres == 240 || xres == 480) {
981 										column = mx / tilew;
982 										row = (my - 2 * tileh) / tileh;
983 									}
984 
985 									#ifdef DEBUG
986 									printf("row column : %i %i\n", row, column);
987 									#endif
988 
989 									/* Don't allow replacing of the end points. */
990 									if (boardarray[row][column] > 1) {
991 										/* Place pipe piece from start of preview array. */
992 										if (boardarray[row][column] != NULLPIPEVAL) {
993 											score = score + PIPEOVERWRITESCORE;
994 										} else {
995 											score = score + PIPEPLACEMENTSCORE;
996 										}
997 										boardarray[row][column] = previewarray[0];
998 										/* Move all preview pieces down 1 place. */
999 										for (count = 0; count < PREVIEWARRAYSIZE - 1; count++) {
1000 											previewarray[count] = previewarray[count + 1];
1001 										}
1002 										/* Add a new preview piece at the end. */
1003 										previewarray[PREVIEWARRAYSIZE - 1] = getnextpipepiece();
1004 										/* Mark tile for drawing and redraw everything related */
1005 										drawpipearray[0][0] = row; drawpipearray[0][1] = column; drawpipearray[0][2] = FALSE;
1006 										drawpipearray[1][0] = NULLPIPEVAL;
1007 										redraw = redraw | REDRAWTILE | REDRAWPIPE | REDRAWSCORE | REDRAWPREVIEW;
1008 									} else if (boardarray[row][column] == 0) {
1009 										score = score + gametime * FILLNOWSCORE;
1010 										gametime = 0;
1011 										redraw = redraw | REDRAWSCORE | REDRAWTIMER;
1012 										createdeadpipesarray();
1013 									}
1014 
1015 									#ifdef DEBUG
1016 									printf("boardarray:-\n");
1017 									for (row = 0; row < BOARDH; row++) {
1018 										for (column = 0; column < BOARDW; column++) {
1019 											printf("%3i ", boardarray[row][column]);
1020 										}
1021 										printf("\n");
1022 									}
1023 									printf("\n");
1024 									#endif
1025 								}
1026 							}
1027 							/* Process New Game clicks */
1028 							if (game_mode == GAMEON || game_mode == GAMEFLASHHIGHSCORE || game_mode == GAMEOVER) {
1029 								if (((xres == 320 || xres == 640) && (mx >= 0) && (mx < 3 * tilew) && (my >= 9.25 * tileh) && (my < 9.75 * tileh)) || ((xres == 240 || xres == 480) && (mx >= 6.9 * tilew) && (mx < 9.9 * tilew) && (my >= 12.43 * tileh) && (my < 12.93 * tileh))) {
1030 									/* Initialise new game */
1031 									initialise_new_game();
1032 									#ifdef DEBUG
1033 									printf("New Game\n");
1034 									#endif
1035 								}
1036 							}
1037 							/* Process Fill clicks */
1038 							if (game_mode == GAMEON) {
1039 								if (((xres == 320 || xres == 640) && (mx >= 0) && (mx < 1 * tilew) && (my >= 7.25 * tileh) && (my < 7.75 * tileh)) || ((xres == 240 || xres == 480) && (mx >= 4 * tilew) && (mx < 5 * tilew) && (my >= 12.43 * tileh) && (my < 12.93 * tileh))) {
1040 									score = score + gametime * FILLNOWSCORE;
1041 									gametime = 0;
1042 									redraw = redraw | REDRAWSCORE | REDRAWTIMER;
1043 									createdeadpipesarray();
1044 									#ifdef DEBUG
1045 									printf("Fill\n");
1046 									#endif
1047 								}
1048 							}
1049 							/* Process High Score clicks */
1050 							if (game_mode == GAMEON || game_mode == GAMEFLASHHIGHSCORE || game_mode == GAMEOVER) {
1051 								if (((xres == 320 || xres == 640) && (mx >= 0) && (mx < 3 * tilew) && (my >= 0.25 * tileh) && (my < 0.75 * tileh)) || ((xres == 240 || xres == 480) && (mx >= 3.7 * tilew) && (mx < 6.7 * tilew) && (my >= 0.25 * tileh) && (my < 0.75 * tileh))) {
1052 									initialise_new_game();
1053 									/* Copy the highscoreboard into the board array */
1054 									for (row = 0; row < BOARDH; row++) {
1055 										for (column = 0; column < BOARDW; column++) {
1056 											boardarray[row][column] = highscoreboard[0][row * BOARDH + column];
1057 										}
1058 									}
1059 									gametime = 0;
1060 									disablescoring = TRUE;	/* This is only used here to prevent the score from incrementing whilst filling. */
1061 									createdeadpipesarray();
1062 									#ifdef DEBUG
1063 									printf("High Score\n");
1064 									#endif
1065 								}
1066 							}
1067 							/* Process Help clicks */
1068 							if (game_mode == GAMEON || game_mode == GAMEFLASHHIGHSCORE || game_mode == GAMEOVER) {
1069 								if (((xres == 320 || xres == 640) && (mx >= 0) && (mx < 1.4 * tilew) && (my >= 8.25 * tileh) && (my < 8.75 * tileh)) || ((xres == 240 || xres == 480) && (mx >= 5.25 * tilew) && (mx < 6.65 * tilew) && (my >= 12.43 * tileh) && (my < 12.93 * tileh))) {
1070 									previous_game_mode = game_mode;
1071 									game_mode = GAMESHOWHELP;
1072 									redraw = redraw | REDRAWHELP;
1073 									#ifdef DEBUG
1074 									printf("Help\n");
1075 									#endif
1076 								}
1077 							}
1078 							/* Process Help->Left clicks.
1079 							   I've purposely made the hit area big. */
1080 							if (game_mode == GAMESHOWHELP) {
1081 								if (((xres == 320 || xres == 640) && (mx >= xres - BOARDW * tilew) && (mx < xres - (BOARDW - 1) * tilew) && (my >= (BOARDH - 1) * tileh) && (my < BOARDH * tileh)) || ((xres == 240 || xres == 480) && (mx >= 0) && (mx < 1 * tilew) && (my >= (BOARDH - 1) * tileh + 2 * tileh) && (my < BOARDH * tileh + 2 * tileh))) {
1082 									manage_help_input(SDLK_LEFT);
1083 								}
1084 							}
1085 							/* Process Help->Right clicks.
1086 							   I've purposely made the hit area big. */
1087 							if (game_mode == GAMESHOWHELP) {
1088 								if (((xres == 320 || xres == 640) && (mx >= xres - 1 * tilew) && (mx < xres) && (my >= (BOARDH - 1) * tileh) && (my < BOARDH * tileh)) || ((xres == 240 || xres == 480) && (mx >= xres - 1 * tilew) && (mx < xres) && (my >= (BOARDH - 1) * tileh + 2 * tileh) && (my < BOARDH * tileh + 2 * tileh))) {
1089 									manage_help_input(SDLK_RIGHT);
1090 								}
1091 							}
1092 							/* Process Help->Exit clicks */
1093 							if (game_mode == GAMESHOWHELP) {
1094 								if (((xres == 320 || xres == 640) && (mx >= xres - 5.6 * tilew) && (mx < xres - 4.4 * tilew) && (my >= yres - 0.75 * tileh) && (my < yres - 0.25 * tileh)) || ((xres == 240 || xres == 480) && (mx >= xres - 5.6 * tilew) && (mx < xres - 4.4 * tilew) && (my >= (BOARDH - 0.75) * tileh + 2 * tileh) && (my < (BOARDH - 0.25) * tileh + 2 * tileh))) {
1095 									manage_help_input(SDLK_ESCAPE);
1096 								}
1097 							}
1098 							break;
1099 						default:
1100 							break;
1101 					}
1102 				}
1103 			default:
1104 				break;
1105 		}
1106 	}
1107 }
1108 
1109 /***************************************************************************
1110  * Manage Help Input                                                       *
1111  ***************************************************************************/
1112 /* This manages all user input relating to Help. */
1113 
manage_help_input(int input)1114 void manage_help_input(int input) {
1115 	int rowloop, colloop, count = 0, leakypipefound = FALSE;
1116 	int nomorepipes, passcounter = FILLEDCOUNTERBASE, filled = TRUE, endpipefound = FALSE;
1117 
1118 	switch(input) {
1119 		case SDLK_ESCAPE:
1120 			game_mode = previous_game_mode;
1121 			redraw = REDRAWALL;
1122 			if (game_mode == GAMEFLASHHIGHSCORE || game_mode == GAMEOVER) {
1123 				/* I originally wrote this game in Javascript for a web browser
1124 				   and it wasn't designed to have anything drawn over the top of
1125 				   it, so the pipe network needs to be rebuilt. At this point the
1126 				   deadpipesarray still holds the filled pipe network so it just
1127 				   needs to be decoded.*/
1128 				do {
1129 					nomorepipes = TRUE;
1130 					for (rowloop = 0; rowloop < BOARDH; rowloop++) {
1131 						for (colloop = 0; colloop < BOARDW; colloop++) {
1132 							if (deadpipesarray[rowloop][colloop] == passcounter || deadpipesarray[rowloop][colloop] - LEAKYPIPEVAL == passcounter) {
1133 								/* Mark pipe to be drawn */
1134 								drawpipearray[count][0] = rowloop;
1135 								drawpipearray[count][1] = colloop;
1136 								drawpipearray[count][2] = filled;
1137 								count++;
1138 								/* If a leaky pipe is found then after this pass all pipes will be unfilled. */
1139 								if (deadpipesarray[rowloop][colloop] >= FILLEDCOUNTERBASE + LEAKYPIPEVAL) {
1140 									leakypipefound = TRUE;
1141 								}
1142 								/* At least one pipe was found for this pass */
1143 								nomorepipes = FALSE;
1144 							} else if (deadpipesarray[rowloop][colloop] == DEADPIPEVAL && boardarray[rowloop][colloop] == 1 && !endpipefound) {
1145 								/* Mark the unvisited end pipe for drawing */
1146 								drawpipearray[count][0] = rowloop;
1147 								drawpipearray[count][1] = colloop;
1148 								drawpipearray[count][2] = FALSE;
1149 								count++;
1150 								endpipefound = TRUE;	/* Only record it once */
1151 							}
1152 						}
1153 					}
1154 					if(leakypipefound) filled = FALSE;	/* Draw unfilled pipes from now on */
1155 					passcounter++;
1156 				} while(!nomorepipes);
1157 				drawpipearray[count][0] = NULLPIPEVAL;
1158 				redraw = (redraw | REDRAWPIPE) ^ REDRAWALLPIPES;
1159 			}
1160 			#ifdef DEBUG
1161 			printf("Help->Exit\n");
1162 			#endif
1163 			break;
1164 		case SDLK_LEFT:
1165 			if(helppage > 0) {
1166 				helppage = helppage - 1;
1167 				redraw = redraw | REDRAWHELP;
1168 				#ifdef DEBUG
1169 				printf("Help->Left\n");
1170 				#endif
1171 			}
1172 			break;
1173 		case SDLK_RIGHT:
1174 			if(helppage < HELPPAGES - 1) {
1175 				helppage = helppage + 1;
1176 				redraw = redraw | REDRAWHELP;
1177 				#ifdef DEBUG
1178 				printf("Help->Right\n");
1179 				#endif
1180 			}
1181 			break;
1182 		default:
1183 			break;
1184 	}
1185 }
1186 
1187 /***************************************************************************
1188  * Create Dead Pipes Array                                                 *
1189  ***************************************************************************/
1190 /* This is the main guts of the game. Originally I wrote it in JavaScript for
1191    use in a browser and have simply pasted it here and converted it.
1192    I believe it's quite clever and I found it very enjoyable to write, having
1193    no idea how the pipe-filling would be accomplished. Basically a point is
1194    created at the start pipe and proceeds to travel through any connected
1195    pipes and splits at junctions. Each pipe that is filled is given a number
1196    starting at 20 and is incremented as the network fills. This is used to
1197    animate the fill with a timer so that all pipes marked 20 get shown, then
1198    next timer event all 21s get shown and so on. Leaky pipes are marked and
1199    so are dead pipes (those with no connection to the network). Enable DEBUG
1200    and look at the array dump in the console for a better understanding. */
1201 
createdeadpipesarray(void)1202 void createdeadpipesarray(void) {
1203 	int count = 0, rowloop = 0, colloop = 0;
1204 	int pointexists = FALSE, endreached = FALSE, pointsconverge = FALSE;
1205 	int leakcount = 0, deadcount = 0, freepointer = 0;
1206 	int filledcounter = FILLEDCOUNTERBASE;
1207 	int north = FALSE, south = FALSE, east = FALSE, west = FALSE;
1208 	int targety = 0, targetx = 0;
1209 	int targettype = NULLPIPEVAL, targetvalid = FALSE, targetvisited = FALSE;
1210 	/* --- Create 2 dimensional array for the route tracing points. --- */
1211 	int pointsarray[POINTSARRAYSIZE][4];
1212 	for (rowloop = 0; rowloop < POINTSARRAYSIZE; rowloop++) {
1213 		/* Array Format: y|x|direction|passcounter. */
1214 		pointsarray[rowloop][0] = pointsarray[rowloop][1] = pointsarray[rowloop][3] = 0;
1215 		pointsarray[rowloop][2] = NULLPIPEVAL;	/* dead point. */
1216 	}
1217 
1218 	/* Find endpoints in game board array. */
1219 	for (rowloop = 0; rowloop < BOARDH; rowloop++) {
1220 		for (colloop = 0; colloop < BOARDW; colloop++) {
1221 			if (boardarray[rowloop][colloop] == 0) {
1222 				/* Create a single point at start heading west (0=n|1=e|2=s|3=w). */
1223 				pointsarray[POINTSARRAYSIZE - 1][0] = rowloop;
1224 				pointsarray[POINTSARRAYSIZE - 1][1] = colloop;
1225 				pointsarray[POINTSARRAYSIZE - 1][2] = 3;
1226 				pointsarray[POINTSARRAYSIZE - 1][3] = filledcounter;
1227 			}
1228 			/* Duplicate the game board array into the dead pipes array. */
1229 			deadpipesarray[rowloop][colloop] = boardarray[rowloop][colloop];
1230 		}
1231 	}
1232 	/* MAIN LOOP. Do this while points exist (no points means no more routes). */
1233 	do {
1234 		pointexists = FALSE;
1235 		for (rowloop = 0; rowloop < POINTSARRAYSIZE; rowloop++) {
1236 			if (pointsarray[rowloop][2] != NULLPIPEVAL && pointsarray[rowloop][3] == filledcounter) {
1237 				/* Get target yx.*/
1238 				switch (pointsarray[rowloop][2]) {	/* point direction. */
1239 					case 0 :	/* north. */
1240 						targety = pointsarray[rowloop][0] - 1;
1241 						targetx = pointsarray[rowloop][1];
1242 						break;
1243 					case 1 :	/* east. */
1244 						targety = pointsarray[rowloop][0];
1245 						targetx = pointsarray[rowloop][1] + 1;
1246 						break;
1247 					case 2 :	/* south. */
1248 						targety = pointsarray[rowloop][0] + 1;
1249 						targetx = pointsarray[rowloop][1];
1250 						break;
1251 					case 3 :	/* west. */
1252 						targety = pointsarray[rowloop][0];
1253 						targetx = pointsarray[rowloop][1] - 1;
1254 						break;
1255 				}
1256 				/* Get target pipe type. */
1257 				if (targety < 0 || targety >= BOARDH || targetx < 0 || targetx >= BOARDW) {
1258 					targettype = NULLPIPEVAL;	/* targets outside the game board are invalid. */
1259 				} else {
1260 					targettype = boardarray[targety][targetx];
1261 				}
1262 				/* Get direction information on the target piece. */
1263 				switch (targettype) {
1264 					case 0 :
1265 						north = FALSE; east = FALSE; south = FALSE; west = TRUE;
1266 						break;
1267 					case 1 :
1268 						north = FALSE; east = TRUE; south = FALSE; west = FALSE;
1269 						break;
1270 					case 2 :
1271 						north = TRUE; east = FALSE; south = FALSE; west = TRUE;
1272 						break;
1273 					case 3 :
1274 						north = FALSE; east = FALSE; south = TRUE; west = TRUE;
1275 						break;
1276 					case 4 :
1277 						north = FALSE; east = TRUE; south = TRUE; west = FALSE;
1278 						break;
1279 					case 5 :
1280 						north = TRUE; east = TRUE; south = FALSE; west = FALSE;
1281 						break;
1282 					case 6 :
1283 						north = TRUE; east = FALSE; south = TRUE; west = TRUE;
1284 						break;
1285 					case 7 :
1286 						north = FALSE; east = TRUE; south = TRUE; west = TRUE;
1287 						break;
1288 					case 8 :
1289 						north = TRUE; east = TRUE; south = TRUE; west = FALSE;
1290 						break;
1291 					case 9 :
1292 						north = TRUE; east = TRUE; south = FALSE; west = TRUE;
1293 						break;
1294 					case 10 :
1295 						north = TRUE; east = TRUE; south = TRUE; west = TRUE;
1296 						break;
1297 					case 11 :
1298 						north = FALSE; east = TRUE; south = FALSE; west = TRUE;
1299 						break;
1300 					case 12 :
1301 						north = TRUE; east = FALSE; south = TRUE; west = FALSE;
1302 						break;
1303 					case 13 :
1304 						north = FALSE; east = FALSE; south = FALSE; west = TRUE;
1305 						break;
1306 					case 14 :
1307 						north = TRUE; east = FALSE; south = FALSE; west = FALSE;
1308 						break;
1309 					case 15 :
1310 						north = FALSE; east = TRUE; south = FALSE; west = FALSE;
1311 						break;
1312 					case 16 :
1313 						north = FALSE; east = FALSE; south = TRUE; west = FALSE;
1314 						break;
1315 					default :
1316 						north = FALSE; east = FALSE; south = FALSE; west = FALSE;
1317 						break;
1318 				}
1319 				/* Get validity of target move. */
1320 				targetvalid = FALSE;
1321 				if (pointsarray[rowloop][2] == 0 && south == TRUE) targetvalid = TRUE;
1322 				if (pointsarray[rowloop][2] == 1 && west == TRUE) targetvalid = TRUE;
1323 				if (pointsarray[rowloop][2] == 2 && north == TRUE) targetvalid = TRUE;
1324 				if (pointsarray[rowloop][2] == 3 && east == TRUE) targetvalid = TRUE;
1325 				/* Get visited status of target pipe. */
1326 				targetvisited = FALSE;
1327 				if (targetvalid) {	/* don't try and reference array elements using -1 ;) */
1328 					if (deadpipesarray[targety][targetx] >= FILLEDCOUNTERBASE && deadpipesarray[targety][targetx] != NULLPIPEVAL) targetvisited = TRUE;
1329 				}
1330 				/* Now that we have all the info we make the MAIN DECISIONS HERE. */
1331 				/* If source is THE endpoint... */
1332 				if (boardarray[pointsarray[rowloop][0]][pointsarray[rowloop][1]] == 1) {
1333 					if (deadpipesarray[pointsarray[rowloop][0]][pointsarray[rowloop][1]] >= 0 && deadpipesarray[pointsarray[rowloop][0]][pointsarray[rowloop][1]] < FILLEDCOUNTERBASE) deadpipesarray[pointsarray[rowloop][0]][pointsarray[rowloop][1]] = filledcounter;	/* mark source as filled. */
1334 					pointsarray[rowloop][2] = NULLPIPEVAL;	/* kill current point. */
1335 					endreached = TRUE;
1336 				} else {
1337 					/* ElseIf target is valid and not visited... */
1338 					if (targetvalid && !targetvisited) {
1339 						if (deadpipesarray[pointsarray[rowloop][0]][pointsarray[rowloop][1]] >= 0 && deadpipesarray[pointsarray[rowloop][0]][pointsarray[rowloop][1]] < FILLEDCOUNTERBASE) deadpipesarray[pointsarray[rowloop][0]][pointsarray[rowloop][1]] = filledcounter;	/* mark source as filled. */
1340 						pointsarray[rowloop][2] = NULLPIPEVAL;	/* kill current point. */
1341 						/* Create a new point at target for each direction. */
1342 						/* Merge converging paths, caused when 2 sources converge on the same target at the same time. */
1343 						if (north) {
1344 							pointsconverge = FALSE;
1345 							for (count = 0; count < POINTSARRAYSIZE; count++) {
1346 								if (pointsarray[count][2] != NULLPIPEVAL) {
1347 									/* We don't want 2 points in the same square going in the same direction. */
1348 									if (pointsarray[count][0] == targety && pointsarray[count][1] == targetx && pointsarray[count][2] == 0) {
1349 										pointsconverge = TRUE;
1350 									}
1351 								} else {
1352 									freepointer = count;	/* record this as we'll use it to store the new point. */
1353 								}
1354 							}
1355 							if (!pointsconverge) {
1356 								pointsarray[freepointer][0] = targety; pointsarray[freepointer][1] = targetx;
1357 								pointsarray[freepointer][2] = 0; pointsarray[freepointer][3] = filledcounter + 1;	/* process it next do-while iteration. */
1358 								pointexists = TRUE;
1359 							}
1360 						}
1361 						if (east) {
1362 							pointsconverge = FALSE;
1363 							for (count = 0; count < POINTSARRAYSIZE; count++) {
1364 								if (pointsarray[count][2] != NULLPIPEVAL) {
1365 									/* We don't want 2 points in the same square going in the same direction. */
1366 									if (pointsarray[count][0] == targety && pointsarray[count][1] == targetx && pointsarray[count][2] == 1) {
1367 										pointsconverge = TRUE;
1368 									}
1369 								} else {
1370 									freepointer = count;	/* record this as we'll use it to store the new point. */
1371 								}
1372 							}
1373 							if (!pointsconverge) {
1374 								pointsarray[freepointer][0] = targety; pointsarray[freepointer][1] = targetx;
1375 								pointsarray[freepointer][2] = 1; pointsarray[freepointer][3] = filledcounter + 1;	/* process it next do-while iteration. */
1376 								pointexists = TRUE;
1377 							}
1378 						}
1379 						if (south) {
1380 							pointsconverge = FALSE;
1381 							for (count = 0; count < POINTSARRAYSIZE; count++) {
1382 								if (pointsarray[count][2] != NULLPIPEVAL) {
1383 									/* We don't want 2 points in the same square going in the same direction. */
1384 									if (pointsarray[count][0] == targety && pointsarray[count][1] == targetx && pointsarray[count][2] == 2) {
1385 										pointsconverge = TRUE;
1386 									}
1387 								} else {
1388 									freepointer = count;	/* record this as we'll use it to store the new point. */
1389 								}
1390 							}
1391 							if (!pointsconverge) {
1392 								pointsarray[freepointer][0] = targety; pointsarray[freepointer][1] = targetx;
1393 								pointsarray[freepointer][2] = 2; pointsarray[freepointer][3] = filledcounter + 1;	/* process it next do-while iteration. */
1394 								pointexists = TRUE;
1395 							}
1396 						}
1397 						if (west) {
1398 							pointsconverge = FALSE;
1399 							for (count = 0; count < POINTSARRAYSIZE; count++) {
1400 								if (pointsarray[count][2] != NULLPIPEVAL) {
1401 									/* We don't want 2 points in the same square going in the same direction. */
1402 									if (pointsarray[count][0] == targety && pointsarray[count][1] == targetx && pointsarray[count][2] == 3) {
1403 										pointsconverge = TRUE;
1404 									}
1405 								} else {
1406 									freepointer = count;	/* record this as we'll use it to store the new point. */
1407 								}
1408 							}
1409 							if (!pointsconverge) {
1410 								pointsarray[freepointer][0] = targety; pointsarray[freepointer][1] = targetx;
1411 								pointsarray[freepointer][2] = 3; pointsarray[freepointer][3] = filledcounter + 1;	/* process it next do-while iteration. */
1412 								pointexists = TRUE;
1413 							}
1414 						}
1415 					} else {
1416 						/* ElseIf target is valid and visited... */
1417 						if (targetvalid && targetvisited) {
1418 							if (deadpipesarray[pointsarray[rowloop][0]][pointsarray[rowloop][1]] >= 0 && deadpipesarray[pointsarray[rowloop][0]][pointsarray[rowloop][1]] < FILLEDCOUNTERBASE) deadpipesarray[pointsarray[rowloop][0]][pointsarray[rowloop][1]] = filledcounter;	/* mark source as filled. */
1419 							pointsarray[rowloop][2] = NULLPIPEVAL;	/* kill current point. */
1420 						} else {
1421 							/* ElseIf target is not valid... */
1422 							if  (!targetvalid) {
1423 								deadpipesarray[pointsarray[rowloop][0]][pointsarray[rowloop][1]] = filledcounter + LEAKYPIPEVAL;	/* mark source as leaky retaining fill count (important). */
1424 								pointsarray[rowloop][2] = NULLPIPEVAL;	/* kill current point. */
1425 								leakcount++;
1426 							}
1427 						}
1428 					}
1429 				}
1430 			}
1431 		}
1432 		filledcounter++;
1433 	} while (pointexists);
1434 
1435 	/* MARK DEAD PIPES. The easy bit :) */
1436 	deadcount = 0;
1437 	for (rowloop = 0; rowloop < BOARDH; rowloop++) {
1438 		for (colloop = 0; colloop < BOARDW; colloop++) {
1439 			if (deadpipesarray[rowloop][colloop] >= 0 && deadpipesarray[rowloop][colloop] < FILLEDCOUNTERBASE) {
1440 				deadpipesarray[rowloop][colloop] = DEADPIPEVAL;
1441 				deadcount++;	/* count can include endpoint if it is unvisited. */
1442 			}
1443 		}
1444 	}
1445 
1446 	#ifdef DEBUG
1447 	printf("deadpipesarray:-\n");
1448 	for (rowloop = 0; rowloop < BOARDH; rowloop++) {
1449 		for (colloop = 0; colloop < BOARDW; colloop++) {
1450 			printf("%3i ", deadpipesarray[rowloop][colloop]);
1451 		}
1452 		printf("\n");
1453 	}
1454 	printf("\n");
1455 	#endif
1456 
1457 	cleardeadpipesy = 0;
1458 	cleardeadpipesx = 0;
1459 	cleardeadpipes_ticks = 0;
1460 	game_mode = GAMECLEARDEADPIPES; /* And off we go next main loop cycle... */
1461 }
1462 
1463 /***************************************************************************
1464  * Clear Dead Pipes                                                        *
1465  ***************************************************************************/
1466 /* This clears one dead pipe at a time from the board array and the screen
1467    and is designed to be called from a timer so that it appears animated. */
1468 
cleardeadpipes(void)1469 void cleardeadpipes(void) {
1470 	int deadpipefound = FALSE, nomorepipes = FALSE;
1471 
1472 	do {
1473 		/* Officially if the endpoint is unvisited it's dead, but we'll leave it onscreen anyway. */
1474 		if (deadpipesarray[cleardeadpipesy][cleardeadpipesx] == DEADPIPEVAL && boardarray[cleardeadpipesy][cleardeadpipesx] != 1) {
1475 			/* Erase dead pipe from the screen. */
1476 			drawpipearray[0][0] = cleardeadpipesy; drawpipearray[0][1] = cleardeadpipesx;
1477 			drawpipearray[1][0] = NULLPIPEVAL;
1478 			redraw = redraw | REDRAWTILE;
1479 			/* Erase dead pipe from the board array. */
1480 			boardarray[cleardeadpipesy][cleardeadpipesx] = NULLPIPEVAL;
1481 			score = score + DEADPIPESCORE;
1482 			redraw = redraw | REDRAWSCORE;
1483 			deadpipefound = TRUE;
1484 		}
1485 		/* Work our way from top left to bottom right. */
1486 		cleardeadpipesx++;
1487 		if (cleardeadpipesx >= BOARDW) {
1488 			cleardeadpipesx = 0; cleardeadpipesy++;
1489 			if (cleardeadpipesy >= BOARDH) nomorepipes = TRUE;
1490 		}
1491 	} while (!deadpipefound && !nomorepipes);
1492 	if (nomorepipes) {
1493 		fillpipespasscounter = FILLEDCOUNTERBASE;
1494 		fillpipes_ticks = 0;
1495 		game_mode = GAMEFILLPIPES;	/* And off we go next main loop cycle... */
1496 	}
1497 }
1498 
1499 /***************************************************************************
1500  * Fill Pipes                                                              *
1501  ***************************************************************************/
1502 /* This fills one or several pipes at a time. */
1503 
fillpipes(void)1504 void fillpipes(void) {
1505 	int rowloop, colloop, count = 0;
1506 	int leakypipefound, nomorepipes;
1507 
1508 	/* Show all filled pipes onscreen for this passcounter */
1509 	leakypipefound = FALSE;
1510 	nomorepipes = TRUE;
1511 	for (rowloop = 0; rowloop < BOARDH; rowloop++) {
1512 		for (colloop = 0; colloop < BOARDW; colloop++) {
1513 			if (deadpipesarray[rowloop][colloop] == fillpipespasscounter || deadpipesarray[rowloop][colloop] - LEAKYPIPEVAL == fillpipespasscounter) {
1514 				/* Draw filled pipe. */
1515 				drawpipearray[count][0] = rowloop;
1516 				drawpipearray[count][1] = colloop;
1517 				drawpipearray[count][2] = TRUE;
1518 				drawpipearray[count + 1][0] = NULLPIPEVAL;
1519 				count++;
1520 				redraw = redraw | REDRAWTILE | REDRAWPIPE;
1521 				/* When displaying the highscoreboard ignore scoring */
1522 				if (!disablescoring) {
1523 					score = score + FILLEDPIPESCORE;
1524 					redraw = redraw | REDRAWSCORE;
1525 				}
1526 				/* If a leaky pipe is found then flag it */
1527 				if (deadpipesarray[rowloop][colloop] >= FILLEDCOUNTERBASE + LEAKYPIPEVAL) leakypipefound = TRUE;
1528 			} else {
1529 				if (deadpipesarray[rowloop][colloop] > fillpipespasscounter && deadpipesarray[rowloop][colloop] < DEADPIPEVAL) nomorepipes = FALSE;
1530 			}
1531 		}
1532 	}
1533 
1534 	fillpipespasscounter++;
1535 
1536 	if (leakypipefound || nomorepipes) {
1537 		/* Ok, last bit: high score, again ignoring whilst displaying the highscoreboard */
1538 		if (!disablescoring && score > highscoretable[0]) {
1539 			highscoretable[0] = score;
1540 			/* Copy the board into the highscoreboard */
1541 			for (rowloop = 0; rowloop < BOARDH; rowloop++) {
1542 				for (colloop = 0; colloop < BOARDW; colloop++) {
1543 					highscoreboard[0][rowloop * BOARDH + colloop] = boardarray[rowloop][colloop];
1544 				}
1545 			}
1546 			redraw = redraw | REDRAWHIGHSCORE;
1547 			flashhighscore_ticks = SDL_GetTicks();
1548 			game_mode = GAMEFLASHHIGHSCORE;
1549 
1550 			#ifdef DEBUG
1551 			printf("Saving resource file -> ");
1552 			#endif
1553 
1554 			save_rc_file();	/* This saves the new highscore[s] */
1555 		} else {
1556 			game_mode = GAMEOVER;
1557 		}
1558 	}
1559 }
1560 
1561 /***************************************************************************
1562  * Read Resource File                                                      *
1563  ***************************************************************************/
1564 
read_rc_file(void)1565 void read_rc_file(void) {
1566 	char buffer[256];
1567 	FILE* file;
1568 	int result, value, count;
1569 
1570 	strcpy(buffer, user_home_dir);
1571 	strcat(buffer, "/");
1572 	strcat(buffer, RESOURCEFILE);
1573 
1574 	#ifdef DEBUG
1575 	printf("%s\n", buffer);
1576 	#endif
1577 
1578 	if ((file = fopen(buffer,"r")) == NULL) {
1579 		printf("%s: Cannot read from file %s\n", __func__, buffer);
1580 		return;
1581 	}
1582 
1583 	result = fscanf(file,"%s", buffer);	/* [highscore0] */
1584 	if (result != 1 || strcmp(buffer, "[highscore0]") != 0) {
1585 		printf("%s: Data from resource file is unreliable\n", __func__);
1586 		fclose(file);
1587 		return;
1588 	} else {
1589 		#ifdef DEBUG
1590 		printf("%s\n", buffer);
1591 		#endif
1592 	}
1593 	result = fscanf(file,"%i", &value);	/* highscore0 */
1594 	if (result != 1) {
1595 		printf("%s: Data from resource file is unreliable\n", __func__);
1596 		fclose(file);
1597 		return;
1598 	} else {
1599 		#ifdef DEBUG
1600 		printf("%d\n", value);
1601 		#endif
1602 		highscoretable[0] = value;
1603 	}
1604 
1605 	result = fscanf(file,"%s", buffer);	/* [highscoreboard0] */
1606 	if (result != 1 || strcmp(buffer, "[highscoreboard0]") != 0) {
1607 		printf("%s: Data from resource file is unreliable\n", __func__);
1608 		fclose(file);
1609 		return;
1610 	} else {
1611 		#ifdef DEBUG
1612 		printf("%s\n", buffer);
1613 		#endif
1614 	}
1615 	for (count = 0; count < BOARDH * BOARDW; count++) {
1616 		result = fscanf(file,"%i", &value);	/* pipe piece id */
1617 		if (result != 1) {
1618 			printf("%s: Data from resource file is unreliable\n", __func__);
1619 			fclose(file);
1620 			return;
1621 		} else {
1622 			#ifdef DEBUG
1623 			if (count > 0 && count % BOARDH == 0) printf("\n");
1624 			printf("%3i ", value);
1625 			#endif
1626 			highscoreboard[0][count] = value;
1627 		}
1628 	}
1629 	#ifdef DEBUG
1630 	printf("\n");
1631 	#endif
1632 
1633 	fclose(file);
1634 }
1635 
1636 /***************************************************************************
1637  * Save Resource File                                                      *
1638  ***************************************************************************/
1639 
save_rc_file(void)1640 void save_rc_file(void) {
1641 	char buffer[256];
1642 	FILE* file;
1643 	int count;
1644 
1645 	strcpy(buffer, user_home_dir);
1646 	strcat(buffer, "/");
1647 	strcat(buffer, RESOURCEFILE);
1648 
1649 	#ifdef DEBUG
1650 	printf("%s\n", buffer);
1651 	#endif
1652 
1653 	if ((file = fopen(buffer,"w")) == NULL) {
1654 		printf("%s: Cannot write to file %s\n", __func__, buffer);
1655 		return;
1656 	}
1657 
1658 	fprintf(file,"[highscore0]\n%i\n", highscoretable[0]);
1659 
1660 	fprintf(file,"[highscoreboard0]\n");
1661 	for (count = 0; count < BOARDH * BOARDW; count++) {
1662 		if (count > 0 && count % BOARDH == 0) fprintf(file,"\n");
1663 		fprintf(file,"%3i ", highscoreboard[0][count]);
1664 	}
1665 	fprintf(file,"\n");
1666 
1667 	fclose(file);
1668 }
1669 
1670 
1671