fixed path to external icons
[shermanaquarium] / sherman-aquarium / shermans / fish.c
1
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "aquarium.h"
8 #include "draw.h"
9 #include "fish.h"
10 #include "bottom.h"
11 #include "soundeffects.h"
12
13
14
15 /* Data for fishes */
16
17 static float fish1_speed[4] = { 1.0, 1.0, 1.0, 1.0 };
18 static float fish2_speed[4] = { 0.6, 0.6, 0.6, 0.6 };
19 static float fish3_speed[4] = { 1.1, 1.1, 1.1, 1.1 };
20 static float fish4_speed[4] = { 1.0, 1.0, 1.0, 1.0 };
21 static float fish5_speed[7] = { 0.8, 0.8, 0.7, 0.5, 0.7, 0.8, 0.8 };
22 static float fish6_speed[4] = { 1.2, 1.2, 1.2, 1.2 };
23
24 static float squid_speed[7] = { 0.1, 3.0, 3.0, 3.0, 3.0, 1.5, 1.0 };
25 static float swordfish_speed[4] = { 1.4, 1.4, 1.4, 1.4 };
26 static float blowfish_speed[4] = { 0.6, 0.6, 0.6, 0.6 };
27 static float ernest_speed[4] = { 0.8, 0.8, 0.8, 0.8 };
28 static float hunter_speed[4] = { 1.1, 1.1, 1.1, 1.1 };
29 static float lori_speed[4] = { 0.8, 0.8, 0.8, 0.8 };
30 static float prey_speed[4] = { 1.3, 1.3, 1.3, 1.3 };
31 static float sherman_speed[14] =
32     { 1.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.5, 1.75, 2.25, 2.5, 2.5, 2.5 };
33 static float fillmore_speed[15] =
34     { 0.7, 0.7, 0.7, 0.7, 0.8, 0.9, 1.0, 1.0, 1.0, 0.7, 0.5, 0.5, 0.5, 0.6, 0.7 };
35
36 static float prey_hunter_speed[7] = {1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5};
37 static float blowup_speed[2] = {0.1, 0.1};
38
39 static float bdweller_speed[4] = {0.01, 0.01, 0.01, 0.01};
40
41
42 static int normal_animation[4] =    { 0, 1, 2, 1 };
43 static int sherman_animation[14] =  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 0 };
44 static int fillmore_animation[15] = { 0, 1, 2, 3, 4, 5, 6, 6, 6, 7, 8, 9, 10, 11,  0 };
45
46 static int squid_animation[7]={ 0, 1, 1, 1, 1, 1, 2};
47 static int fish5_animation[7]={ 0, 0, 1, 2, 1, 0, 0};
48 static int prey_hunter_animation[7]={0, 1, 2, 3, 4, 5, 6};
49
50
51 static Fish_animation fish_animation[NUMOFFISHTYPES] = {
52     {"sherman/fish1.png",     3, 4, normal_animation,   fish1_speed     },
53     {"sherman/fish2.png",     3, 4, normal_animation,   fish2_speed     },
54     {"sherman/fish3.png",     3, 4, normal_animation,   fish3_speed     },
55     {"sherman/fish4.png",     3, 4, normal_animation,   fish4_speed     },
56     {"sherman/fish5.png",     3, 7, fish5_animation,    fish5_speed     },
57     {"sherman/fish6.png",     3, 4, normal_animation,   fish6_speed     },
58     {"sherman/squid.png",     3, 7, squid_animation,    squid_speed     },
59     {"sherman/swordfish.png", 3, 4, normal_animation,   swordfish_speed },
60     {"sherman/blowfish.png",  3, 4, normal_animation,   blowfish_speed  },
61     {"sherman/ernest.png",    3, 4, normal_animation,   ernest_speed    },
62     {"sherman/hunter.png",    3, 4, normal_animation,   hunter_speed    },
63     {"sherman/lori.png",      3, 4, normal_animation,   lori_speed      },
64     {"sherman/prey.png",      3, 4, normal_animation,   prey_speed      },
65     {"sherman/sherman.png",  11,14, sherman_animation,  sherman_speed   },
66     {"sherman/fillmore.png", 12,15, fillmore_animation, fillmore_speed  },
67     {"sherman/bdweller.png",  3, 4, normal_animation,   bdweller_speed  },
68     {"sherman/hawthorne.png", 3, 4, normal_animation,   bdweller_speed  },
69     {"sherman/megan.png",    11,14, sherman_animation,  sherman_speed   },
70
71 };
72
73
74 static Fish *fishes;
75 static SA_Image blowup_data;
76 static SA_Image prey_hunter_data;
77
78 static SA_Image *fish_buffer;
79 static Fish_settings fish_settings;
80
81 static AquariumData *ad;
82 static int scale_diff, num_fish, hunter_is, blowfish_is;
83
84 Fish_settings *fish_get_settings_ptr(void)
85 {
86     return &fish_settings;
87 }
88
89 Fish *fish_get_fishes_ptr(void)
90 {
91     return fishes;
92 }
93
94 void fish_enter(void)
95 {
96     int i;
97
98     for (i = 0; i < fish_settings.num_fish; i++){
99
100     /* completely off the screen, don't bother showing their escape */
101         if ( ((int)fishes[i].tx > (ad->xmax)) || 
102              ((int)fishes[i].tx < -(fishes[i].width)))
103             fishes[i].speed_mul = 0.0;
104         else    
105             fishes[i].speed_mul = 2.5;
106     }
107
108 }
109
110 void fish_leave(void)
111 {
112     int i;
113
114     for (i = 0; i < fish_settings.num_fish; i++)
115         fishes[i].speed_mul = 1.0;
116
117 }
118
119
120 static int sel_fish(int j, int reset)
121 {
122     static int local_fish[NUMOFFISHTYPES];
123
124     if(reset){
125         memset(&local_fish, 0, sizeof(int)*NUMOFFISHTYPES);
126         return 0;
127     }
128
129
130     /* The Bottom fish first */
131     if(fish_settings.bdweller > local_fish[BDWELLER]){
132         local_fish[BDWELLER]++;
133         return BDWELLER;
134     }
135
136     if(fish_settings.hawthorne > local_fish[HAWTHORNE]){
137         local_fish[HAWTHORNE]++;
138         return HAWTHORNE;
139     }
140
141
142     /* FIXME: Should randomize the order */
143
144     if(fish_settings.fish1 > local_fish[FISH1]){
145         local_fish[FISH1]++;
146         return FISH1;
147     }
148
149     if(fish_settings.fish2 > local_fish[FISH2]){
150         local_fish[FISH2]++;
151         return FISH2;
152     }
153
154     if(fish_settings.fish3 > local_fish[FISH3]){
155         local_fish[FISH3]++;
156         return FISH3;
157     }
158
159     if(fish_settings.fish4 > local_fish[FISH4]){
160         local_fish[FISH4]++;
161         return FISH4;
162     }
163
164     if(fish_settings.fish5 > local_fish[FISH5]){
165         local_fish[FISH5]++;
166         return FISH5;
167     }
168
169     if(fish_settings.fish6 > local_fish[FISH6]){
170         local_fish[FISH6]++;
171         return FISH6;
172     }
173
174
175     if(fish_settings.squid > local_fish[SQUID]){
176         local_fish[SQUID]++;
177         return SQUID;
178     }
179
180     if(fish_settings.swordfish > local_fish[SWORDFISH]){
181         local_fish[SWORDFISH]++;
182         return SWORDFISH;
183     }
184
185     if(fish_settings.blowfish > local_fish[BLOWFISH]){
186         local_fish[BLOWFISH]++;
187         return BLOWFISH;
188     }
189
190     if(fish_settings.ernest > local_fish[ERNEST]){
191         local_fish[ERNEST]++;
192         return ERNEST;
193     }
194
195     if(fish_settings.hunter > local_fish[HUNTER]){
196         local_fish[HUNTER]++;
197         return HUNTER;
198     }
199
200     if(fish_settings.lori > local_fish[LORI]){
201         local_fish[LORI]++;
202         return LORI;
203     }
204
205     if(fish_settings.prey > local_fish[PREY]){
206         local_fish[PREY]++;
207         return PREY;
208     }
209
210     if(fish_settings.sherman > local_fish[SHERMAN]){
211         local_fish[SHERMAN]++;
212         return SHERMAN;
213     }
214
215     if(fish_settings.fillmore > local_fish[FILLMORE]){
216         local_fish[FILLMORE]++;
217         return FILLMORE;
218     }
219
220     if(fish_settings.megan > local_fish[MEGAN]){
221         local_fish[MEGAN]++;
222         return MEGAN;
223     }
224     return 0;
225 }
226
227
228 static int get_fish(int start, int wantedfish)
229 {
230     int i;
231     AquariumData *ad;
232     ad = aquarium_get_settings_ptr();
233
234     for(i = start + 1; i < fish_settings.num_fish; i++)
235         if(fishes[i].type == wantedfish) return i;
236   
237     return -1;
238 }
239
240 /* This rouitine handles both the eating fish happening and
241    the swordish hits a blowfish happening. */
242
243 /* 
244    This rountine is the most messy you've seen. Sorry! 
245    But it works ok. :-)
246 */
247
248 static void prey_hunter_hit()
249 {
250     int i, j;
251     int victim_val=-1, doer_val=-1;
252
253     ad = aquarium_get_settings_ptr();
254
255
256     /* FIX ME: Scaling of hunter that eats prey */
257     //    if(fish_settings.scale_diff) return;
258
259     for(i = 0; i < fish_settings.num_fish; i++){
260         doer_val = get_fish(doer_val, HUNTER);
261         if(doer_val == -1) 
262             break;
263
264         /* Check if this one is eating right now. */
265         if(fishes[doer_val].num_animation == 7) 
266             continue;
267
268         victim_val = -1;
269
270         for(j = 0; j < fish_settings.num_fish; j++){
271             victim_val = get_fish(victim_val, PREY);
272             if(victim_val ==- 1) 
273                 break;
274             if(fishes[victim_val].rev == fishes[doer_val].rev) 
275                 continue;
276             
277
278             /* Don't eat already dead fish */
279             if(fishes[victim_val].is_dead) 
280                 continue;
281
282             /* If parts of the prey is beyond the right edge, let it live */
283             if((fishes[victim_val].tx + fishes[victim_val].width) > (ad->xmax + ad->viewpoint_start_x)) 
284                 continue;
285             /* If the fish is below the edge, let it live */
286             if((fishes[victim_val].y) > (ad->ymax + ad->viewpoint_start_y)) 
287                 continue;
288
289             if(fishes[victim_val].tx < (ad->xmin - fishes[victim_val].width)) 
290                 continue;
291
292             /* If the prey is too high, let it live */
293             if((fishes[victim_val].y) < ad->viewpoint_start_y) 
294                 continue;
295
296
297
298       
299             if(abs((fishes[victim_val].y + fishes[victim_val].height) -
300                    (fishes[doer_val].y + fishes[doer_val].height)) > (fishes[doer_val].height / 2)) 
301                 continue;
302
303
304       
305             /* rev=1 prey moves to towards right.*/
306             if(fishes[victim_val].rev){
307
308                 if((fishes[doer_val].tx - fishes[victim_val].tx - fishes[victim_val].width)
309                    > (10 + fishes[victim_val].width) &&
310                    (fishes[doer_val].tx - fishes[victim_val].tx - fishes[victim_val].width)
311                    <(30 + fishes[victim_val].width)){
312                     if((fishes[victim_val].y + fishes[victim_val].height)
313                        >(fishes[doer_val].y + fishes[doer_val].height)) 
314                         fishes[doer_val].y += 2;
315                     if((fishes[victim_val].y + fishes[victim_val].height)
316                        <(fishes[doer_val].y + fishes[doer_val].height)) 
317                         fishes[doer_val].y -= 2;
318                     continue;
319                 }
320
321                 if((fishes[doer_val].tx - fishes[victim_val].tx - fishes[victim_val].width)
322                    > (10 + fishes[victim_val].width))
323                     continue;
324                 if((fishes[doer_val].tx - fishes[victim_val].tx - fishes[victim_val].width)
325                    < fishes[victim_val].width) 
326                     continue;
327
328             }
329             else{
330                 if((fishes[victim_val].tx - fishes[doer_val].width - fishes[doer_val].tx)
331                    > (10 + fishes[victim_val].width) &&
332                    (fishes[victim_val].tx - fishes[doer_val].width - fishes[doer_val].tx)
333                    < (30 + fishes[victim_val].width)){
334
335                     if((fishes[victim_val].y + fishes[victim_val].height)
336                        > (fishes[doer_val].y + fishes[doer_val].height)) 
337                         fishes[doer_val].y += 2;
338                     if((fishes[victim_val].y + fishes[victim_val].height)
339                        < (fishes[doer_val].y + fishes[doer_val].height)) 
340                         fishes[doer_val].y -= 2;
341                     continue;
342                 }
343
344
345                 if((fishes[victim_val].tx - fishes[doer_val].width - fishes[doer_val].tx)
346                    > (10 + fishes[victim_val].width)) 
347                     continue;
348                 if((fishes[victim_val].tx - fishes[doer_val].width - fishes[doer_val].tx)
349                    < fishes[victim_val].width) 
350                     continue;
351             }
352                     
353
354             /* Sometimes the hunter decides not to eat the prey for various reasons. */
355             if(g_rand_int_range(ad->rnd, 0 , 100) > fish_settings.hunter_agr) 
356                 continue;
357
358             //printf("hunter %d eats prey %d!\n",doer_val, victim_val);
359
360         
361
362
363             /* Play scream */
364             sound_eatscream();
365
366             /* Removing eaten prey */
367             aquarium_clean_image((int)fishes[victim_val].tx, fishes[victim_val].y - ad->viewpoint_start_y,
368                                  fishes[victim_val].width, fishes[victim_val].height);
369
370
371             /*      if(doer_val>victim_val) doer_val--;
372
373             fish_settings.num_fish--;
374       
375             for(k=victim_val;k<fish_settings.num_fish;k++){
376                 fishes[k]=fishes[k+1];
377             }
378             */
379
380             fishes[victim_val].is_dead = TRUE;
381
382             /* Towards left */
383       
384             if(!fishes[doer_val].rev)
385                 fishes[doer_val].tx -= (prey_hunter_data.width - fishes[doer_val].width);
386
387             fishes[doer_val].image = &prey_hunter_data;
388             fishes[doer_val].frame = 0;
389             fishes[doer_val].width = prey_hunter_data.width;
390             fishes[doer_val].height =prey_hunter_data.height;
391             fishes[doer_val].animation = prey_hunter_animation;
392             fishes[doer_val].num_animation = 7;
393             fishes[doer_val].speed = prey_hunter_speed;
394             fishes[doer_val].fast_frame_change = 5.0;
395             break;
396       
397         }
398
399     }
400 }
401
402 /* Not quite ok yet...*/
403 static void blowup_hit()
404 {
405
406     int i,j;
407     int victim_val = -1, doer_val = -1;
408     AquariumData *ad;
409
410     ad = aquarium_get_settings_ptr();
411
412
413     for(i = 0;i < fish_settings.num_fish; i++){
414         doer_val = get_fish(doer_val, SWORDFISH);
415         if(doer_val == -1) 
416             break;
417
418         victim_val = -1;
419
420         for(j = 0;j < fish_settings.num_fish; j++){
421             victim_val = get_fish(victim_val, BLOWFISH);
422             if(victim_val == -1) 
423                 break;
424
425             /* Is this blowfish blowing up? - Then take next.*/
426             if(fishes[victim_val].num_animation == 2) 
427                 continue;
428
429             /* Don't bother zombie blowfish */
430             if(fishes[victim_val].is_dead) 
431                 continue;
432        
433             if(fishes[victim_val].rev == fishes[doer_val].rev) 
434                 continue;
435
436
437             /* If parts of the prey is beyond the right edge, let it live */
438             if((fishes[victim_val].tx + fishes[victim_val].width) 
439                > (ad->xmax + ad->viewpoint_start_x)) 
440                 continue;
441             /* If the fish is below the edge, let it live */
442             if((fishes[victim_val].y) > (ad->ymax + ad->viewpoint_start_y)) 
443                 continue;
444
445             if(fishes[victim_val].tx < (ad->xmin-fishes[victim_val].width)) 
446                 continue;
447
448             /* If the prey is too high, let it live */
449             if((fishes[victim_val].y) < ad->viewpoint_start_y)
450                 continue;
451
452       
453             if(abs(fishes[victim_val].y - fishes[doer_val].y)
454                > (fishes[victim_val].height / 2)) 
455                 continue;
456
457
458       
459             /* rev=1 prey moves to towards right.*/
460             if(fishes[victim_val].rev){
461
462                 if((fishes[doer_val].tx - fishes[victim_val].tx - fishes[victim_val].width)
463                    > 0 &&
464                    (fishes[doer_val].tx - fishes[victim_val].tx - fishes[victim_val].width)
465                    < 20){
466                     if((fishes[victim_val].y + fishes[victim_val].height / 2)
467                        > (fishes[doer_val].y + fishes[doer_val].height / 2)) 
468                         fishes[doer_val].y += 2;
469                     if((fishes[victim_val].y + fishes[victim_val].height / 2)
470                        <(fishes[doer_val].y + fishes[doer_val].height / 2))
471                         fishes[doer_val].y -= 2;
472                     continue;
473                 }
474
475                 if((fishes[doer_val].tx - fishes[victim_val].tx - fishes[victim_val].width)
476                    > 0) continue;
477                 if((fishes[doer_val].tx - fishes[victim_val].tx - fishes[victim_val].width)
478                    < -10) continue;
479                 /*
480                   printf("killing from right!\n vx:%d - vy:%d - dx:%d - dy:%d", 
481                   (int)fishes[victim_val].tx, fishes[victim_val].y,
482                   (int)fishes[doer_val].tx, fishes[doer_val].y);
483                 */
484             }
485             else{
486                 if((fishes[victim_val].tx - fishes[doer_val].width - fishes[doer_val].tx)
487                    > 0 &&
488                    (fishes[victim_val].tx - fishes[doer_val].width - fishes[doer_val].tx)
489                    < 20){
490
491                     if((fishes[victim_val].y + fishes[victim_val].height / 2) 
492                        >(fishes[doer_val].y + fishes[doer_val].height / 2)) 
493                         fishes[doer_val].y += 2;
494
495                     if((fishes[victim_val].y + fishes[victim_val].height / 2)
496                        <(fishes[doer_val].y + fishes[doer_val].height / 2)) 
497                         fishes[doer_val].y -= 2;
498
499                     continue;
500                 }
501
502
503                 if((fishes[victim_val].tx - fishes[doer_val].width - fishes[doer_val].tx)
504                    > 0) continue;
505                 if((fishes[victim_val].tx - fishes[doer_val].width - fishes[doer_val].tx)
506                    < -10) continue;
507                 /*
508                   printf("killing from left!\n vx:%d - vy:%d - dx:%d - dy:%d", 
509                   (int)fishes[victim_val].tx, fishes[victim_val].y,
510                   (int)fishes[doer_val].tx, fishes[doer_val].y);
511
512                 */
513             }
514             /*
515               printf("swordfish hit %d blowfish %d!\n",doer_val, victim_val);
516             */
517
518             /* Sometimes the blowfish owns the swordfish money, and that can save its life ;-) */
519             if(g_rand_int_range(ad->rnd, 0, 100) > fish_settings.swordfish_agr) 
520                 continue;
521
522             /* Removing the remains of the poor blowfish */
523             aquarium_clean_image((int)fishes[victim_val].tx, fishes[victim_val].y - ad->viewpoint_start_y,
524                                  fishes[victim_val].width, fishes[victim_val].height);
525
526
527
528             /* Exploding blowfish */
529             sound_explode();
530
531             fishes[victim_val].image = &blowup_data;
532             fishes[victim_val].frame = 0;
533             fishes[victim_val].width = blowup_data.width;
534             fishes[victim_val].height = blowup_data.height;
535             fishes[victim_val].animation = normal_animation;
536             fishes[victim_val].num_animation = 2;
537             fishes[victim_val].speed = blowup_speed;
538             fishes[victim_val].fast_frame_change = 1.0;
539             break;
540       
541         }
542
543     }
544
545 }
546
547
548
549 void fish_update(void)
550 {
551     int i,j;
552     AquariumData *ad;
553     Bottom_settings *bottom;
554
555     ad = aquarium_get_settings_ptr();
556     bottom = bottom_get_settings_ptr();
557
558     if((ad->special_action & 1) && fish_settings.eat)
559         prey_hunter_hit();
560
561     if((ad->special_action & 2) == 2 && fish_settings.explode)
562         blowup_hit();
563
564 #ifdef DEBUG
565     printf("\t\t - Done special hits.\n");
566 #endif
567     
568     for(i = 0;i < fish_settings.num_fish; i++){
569         aquarium_clean_image((int) fishes[i].tx,
570                              fishes[i].y - ad->viewpoint_start_y,
571                              fishes[i].width, fishes[i].height);
572     }
573
574
575     for(i = 0; i < fish_settings.num_fish; i++){
576         if (fishes[i].frame >= (fishes[i].num_animation - 1)){
577             if(fish_settings.eat){
578                 if(fishes[i].image == &prey_hunter_data){
579                     
580                     //printf("Done eating.Continue.\n");
581                     
582             
583                     /* Left movement is ok. */
584                     /*            else fishes[i].tx-=fishes[i].width-fish_buffer[HUNTER].width;*/
585             
586                     if(!fish_settings.scale_diff){
587                         if(fishes[i].rev) 
588                             fishes[i].tx += fishes[i].width - fish_buffer[HUNTER].width;
589                         fishes[i].width = fish_buffer[HUNTER].width;
590                         fishes[i].height = fish_buffer[HUNTER].height;
591                         fishes[i].image = &fish_buffer[HUNTER];
592                     } else {
593                         if(fishes[i].rev) 
594                             fishes[i].tx += fishes[i].width - fish_buffer[hunter_is].width;
595                         fishes[i].width = fish_buffer[hunter_is].width;
596                         fishes[i].height = fish_buffer[hunter_is].height;
597                         fishes[i].image = &fish_buffer[hunter_is];
598                     }
599
600                     fishes[i].animation = normal_animation;
601                     fishes[i].num_animation = 4;
602                     fishes[i].speed = hunter_speed;
603                     fishes[i].fast_frame_change = 1.0;
604                     fishes[i].frame = 0;
605             
606             
607                 }
608             }
609         
610             if(fish_settings.explode) {
611           
612                 if(fishes[i].image == &blowup_data){
613                     //printf("Done blowing up.\n");
614                     fishes[i].is_dead = TRUE;
615
616                     if(!fish_settings.scale_diff){
617                         fishes[i].width = fish_buffer[BLOWFISH].width;
618                         fishes[i].height = fish_buffer[BLOWFISH].height;
619                         fishes[i].image = &fish_buffer[BLOWFISH];
620                     } else {
621                         fishes[i].width = fish_buffer[blowfish_is].width;
622                         fishes[i].height = fish_buffer[blowfish_is].height;
623                         fishes[i].image = &fish_buffer[blowfish_is];
624                     }
625
626                     fishes[i].animation = normal_animation;
627                     fishes[i].num_animation = 4;
628                     fishes[i].speed = prey_speed;
629                     fishes[i].fast_frame_change = 1.0;
630                     fishes[i].frame = 0;
631
632
633                     /*
634                     fish_settings.num_fish--;
635                     for(k=i;k<fish_settings.num_fish;k++){
636                         fishes[k]=fishes[k+1];
637                         }*/
638
639             
640                 }
641             }
642         }
643     }
644     
645     sel_fish(0, TRUE);
646
647     for (i = 0; i < fish_settings.num_fish; i++) {
648
649         if(fishes[i].is_dead == TRUE){
650
651             if(fish_settings.rebirth){
652                 if(g_rand_int_range(ad->rnd, 0, 100) < 20){
653                     //              printf("Rebirth and salvation..\n");
654                     /* Salvation and rebirth...*/
655                     fishes[i].is_dead = FALSE;
656                     fishes[i].frame = g_rand_int_range(ad->rnd, 0, fishes[i].num_animation);
657
658
659                     if(g_rand_boolean(ad->rnd)){
660                         fishes[i].rev = 1;
661                         fishes[i].travel =
662                             g_rand_int_range(ad->rnd, 0, (ad->virtual_aquarium_x - ad->xmax) / 2) +
663                             fishes[i].width;
664                         fishes[i].tx = -fishes[i].width - fishes[i].travel;
665                     } else {
666                         fishes[i].rev = 0;
667                         fishes[i].travel = 
668                             g_rand_int_range(ad->rnd, 0, (ad->virtual_aquarium_x - ad->xmax) / 2) +
669                             fishes[i].width;
670                         fishes[i].tx = ad->xmax + fishes[i].travel;
671                     }
672                     fishes[i].y = g_rand_int_range(ad->rnd, 0, (ad->virtual_aquarium_y - fishes[i].height));
673
674                     fishes[i].speed_mul = 1.0 + g_rand_double_range(ad->rnd, -15.0 / 100.0, 15.0 / 100.0);
675                 }
676
677             } else {
678                 /* Don't draw zombie fish */
679                 continue;
680             }
681         }
682         
683
684         /* frozen fish doesn't need to be handled, or drawn */
685         if (fishes[i].speed_mul == 0)
686             continue;
687
688         if((fishes[i].type == BDWELLER || fishes[i].type == HAWTHORNE) && !bottom->have_sea_floor)
689             continue;
690
691         /* move fish in horizontal direction, left or right */
692         /* Large aquarium, the fishes are shown more seldom */
693         
694     if (!fishes[i].rev) {
695
696             fishes[i].tx -=
697                 (fishes[i].speed[fishes[i].frame]) * (fishes[i].speed_mul * fish_settings.speed / 100);
698
699             if (fishes[i].tx < (-fishes[i].width - fishes[i].travel)) {
700                 /* we moved out of bounds. change direction,
701                  * position, speed. */
702
703
704                 fishes[i].travel = g_rand_int_range(ad->rnd, 0, (ad->virtual_aquarium_x - ad->xmax) / 2) +
705                     fishes[i].width;
706                 fishes[i].tx = -fishes[i].width - fishes[i].travel;
707                 fishes[i].rev = 1;
708
709                 /* If bottom creature, keep the the Y level */
710                 if(fishes[i].type != BDWELLER && fishes[i].type != HAWTHORNE)
711                     fishes[i].y = g_rand_int_range(ad->rnd, 0, ad->virtual_aquarium_y - fishes[i].height);
712                 
713
714                 if (ad->proximity)
715                     fishes[i].speed_mul = 0;
716                 else
717                     fishes[i].speed_mul = 1;
718
719             }
720         } else {
721
722             fishes[i].tx +=
723                 (fishes[i].speed[fishes[i].frame]) * (fishes[i].speed_mul * fish_settings.speed / 100);
724
725
726             if (fishes[i].tx > ad->xmax + fishes[i].travel) {
727                 /* we moved out of bounds. change direction,
728                  * position, speed. */
729
730                 fishes[i].travel = g_rand_int_range(ad->rnd, 0, (ad->virtual_aquarium_x - ad->xmax) / 2) +
731                     fishes[i].width;
732                 fishes[i].tx = ad->xmax + fishes[i].travel;
733                 fishes[i].rev = 0;
734
735                 /* If bottom creature, keep the the Y level */
736                 if(fishes[i].type != BDWELLER && fishes[i].type != HAWTHORNE)
737                     fishes[i].y = g_rand_int_range(ad->rnd, 0, ad->virtual_aquarium_y - fishes[i].height);
738
739                 if (ad->proximity)
740                     fishes[i].speed_mul = 0;
741                 else
742                     fishes[i].speed_mul = 1;
743
744             }
745         }
746
747         /* move fish in vertical position randomly by one pixel up or down */
748         /* If the fish last time moved up or down, larger chance that it does that again. */
749
750         j = g_rand_int_range(ad->rnd, 0, 16);
751
752         /* The bottondweller & hawthorne shall be still ;-) */
753         if(fishes[i].type == BDWELLER || fishes[i].type == HAWTHORNE) 
754             j = 0;
755
756         if (((fishes[i].updown == 1) && (j == 6 || j == 7 || j == 8))
757             || j == 8) {
758             fishes[i].y++;
759             fishes[i].updown = 1;
760         } else if (((fishes[i].updown == -1)
761                     && (j == 12 || j == 13 || j == 14)) || j == 12) {
762             fishes[i].y--;
763             fishes[i].updown = -1;
764         } else
765             fishes[i].updown = 0;
766 #ifdef DEBUG
767         /*      printf("\t\t - Calling draw_fish()\n");*/
768 #endif
769             /* animate fishes using fish_animation array */
770             aquarium_draw_image((int) fishes[i].tx,
771                                 fishes[i].y - ad->viewpoint_start_y,
772                                 fishes[i].animation[fishes[i].frame],
773                                 fishes[i].rev, fishes[i].image);
774
775         /* switch to next swimming frame */
776
777
778         fishes[i].delay += fishes[i].speed[fishes[i].frame] * fishes[i].fast_frame_change;
779 #ifdef DEGUG
780         printf("delay:%f speed:%f frame:%d num_ani:%d anipic:%d\n",
781                fishes[i].delay, fishes[i].speed[fishes[i].frame],fishes[i].frame, fishes[i].num_animation, fishes[i].animation[fishes[i].frame]);
782 #endif
783         if (fishes[i].delay >= (7 * fishes[i].speed[fishes[i].frame])) {
784             if (fishes[i].frame >= (fishes[i].num_animation - 1)){
785                 fishes[i].frame = 0;
786             }     
787             else fishes[i].frame ++;
788             fishes[i].delay = 0;
789         }
790
791     }
792 }
793
794 static void fish_flip(SA_Image *this_fish)
795 {
796     int j, k, ypos;
797
798     if(this_fish->image != NULL){
799
800       this_fish->rev = g_malloc0(this_fish->width * 
801                                  this_fish->full_height * 4 );
802     
803       for(j = 0;j < (this_fish->full_height); j++){
804         ypos = j * this_fish->width * 4;
805         for(k = 0; k < this_fish->width; k++){
806           this_fish->rev[ypos + (this_fish->width - k - 1) * 4]     = this_fish->image[ypos + k * 4];
807           this_fish->rev[ypos + (this_fish->width - k - 1) * 4 + 1] = this_fish->image[ypos + k * 4 + 1];
808           this_fish->rev[ypos + (this_fish->width - k - 1) * 4 + 2] = this_fish->image[ypos + k * 4 + 2];
809           this_fish->rev[ypos + (this_fish->width - k - 1) * 4 + 3] = this_fish->image[ypos + k * 4 + 3];
810         }
811       }
812     }
813 }
814
815
816 void fish_turn(void)
817 {
818   int i, m;
819
820
821   if(fish_settings.scale_diff)
822       m = fish_settings.num_fish;
823   else 
824       m = NUMOFFISHTYPES;
825
826   for(i = 0; i < m; i++){
827       fish_flip(&fish_buffer[i]);
828   }
829
830   fish_flip(&blowup_data);
831   fish_flip(&prey_hunter_data);
832
833 }
834
835
836 void fish_init(void)
837 {
838     int i, num_bottom_fish;
839     int type = 0, special_fish = 0;
840
841     Bottom_settings *bottom_settings;
842     
843     bottom_settings = bottom_get_settings_ptr();
844
845     /* Set up this for the rest of the life */
846     ad = aquarium_get_settings_ptr();
847
848     ad->special_action = 0;
849
850
851     /* Save settings for fish_exit() */
852     scale_diff = fish_settings.scale_diff;
853
854     /* 0 - 30 fishes */
855     if(fish_settings.type == RANDOM_POP_FISH)
856         fish_settings.num_fish = g_rand_int_range(ad->rnd, 1, 30);
857
858     num_fish = fish_settings.num_fish;
859
860     if(fish_settings.scale_diff)
861         fish_buffer = g_malloc0(sizeof(SA_Image) * fish_settings.num_fish);
862     else
863         fish_buffer = g_malloc0(sizeof(SA_Image) * NUMOFFISHTYPES);
864
865
866     fishes = g_malloc0(sizeof(Fish) * fish_settings.num_fish);
867
868     num_bottom_fish = bottom_settings->num_bottom_animals;
869
870     if(num_bottom_fish > num_fish)
871         num_bottom_fish = num_fish;
872
873     for (i = 0; i < fish_settings.num_fish; i++) {
874
875         if(fish_settings.type == RANDOM_FISH || fish_settings.type == RANDOM_POP_FISH) {
876
877             /* FIX ME! Bottom dweller and hawthorne chance !*/
878             if((i<num_bottom_fish) && (bottom_settings->have_sea_floor)) {
879
880                 if(g_rand_boolean(ad->rnd)) 
881                     type = BDWELLER;
882                 else type = HAWTHORNE;
883             }
884             else
885                 do{
886                     type = g_rand_int_range(ad->rnd, 0, NUMOFFISHTYPES); 
887                 } while(type == BDWELLER || type == HAWTHORNE);
888         }
889         else{
890             type = sel_fish(i, FALSE);
891         }
892
893
894         if(type == PREY) special_fish |= 1;
895         if(type == HUNTER) special_fish |= 2;
896         if(type == SWORDFISH) special_fish |= 4;
897         if(type == BLOWFISH) special_fish |= 8;
898
899
900         if(!fish_settings.scale_diff){
901
902             if (fish_buffer[type].image == NULL) {
903                 load_image_n_scale(fish_animation[type].file,
904                                    &fish_buffer[type],
905                                    fish_animation[type].pics,
906                                    fish_settings.scale);
907
908             }
909
910             fishes[i].width = fish_buffer[type].width;
911             fishes[i].height = fish_buffer[type].height;
912
913             fishes[i].image = &fish_buffer[type];
914
915         } else {
916
917             if(type != HUNTER && type != BLOWFISH){
918                 load_image_n_scale(fish_animation[type].file, &fish_buffer[i],
919                                    fish_animation[type].pics,
920                                    abs(fish_settings.scale + (g_rand_int_range(ad->rnd, -15, 15)) * fish_settings.scale / 100) );
921             } else {
922                 if(type == HUNTER) hunter_is = i;
923                 if(type == BLOWFISH) blowfish_is = i;
924
925                 load_image_n_scale(fish_animation[type].file, &fish_buffer[i],
926                                    fish_animation[type].pics,
927                                    fish_settings.scale);
928             }
929
930             fishes[i].width = fish_buffer[i].width;
931             fishes[i].height = fish_buffer[i].height;
932
933             fishes[i].image = &fish_buffer[i];
934
935         }
936
937
938         fishes[i].num_animation = fish_animation[type].frames;
939         fishes[i].animation = fish_animation[type].animation;
940
941         fishes[i].speed = fish_animation[type].speed;
942
943
944         fishes[i].type = type;
945         fishes[i].frame = g_rand_int_range(ad->rnd, 0, fishes[i].num_animation);
946
947         fishes[i].rev = g_rand_boolean(ad->rnd);
948         fishes[i].tx = g_rand_int_range(ad->rnd, 0, ad->virtual_aquarium_x - fishes[i].width);
949
950         fishes[i].speed_mul =  1.0 + g_rand_double_range(ad->rnd, -15.0 / 100.0, 15.0 / 100.0);
951
952
953         fishes[i].fast_frame_change = 1.0;
954
955         fishes[i].is_dead = FALSE;
956
957         fishes[i].updown = 0;
958         fishes[i].travel = g_rand_int_range(ad->rnd, 0, (ad->virtual_aquarium_x - ad->xmax) / 2) + fishes[i].width;
959         fishes[i].y = g_rand_int_range(ad->rnd, 0, ad->virtual_aquarium_y - fishes[i].height);
960
961     }
962
963     
964     if((special_fish & 3) == 3 && fish_settings.eat){
965         load_image_n_scale("sherman/eating.png", 
966                            &prey_hunter_data,
967                            7, fish_settings.scale);
968
969         ad->special_action |= 1;
970     } else
971         prey_hunter_data.pixbuf = NULL;
972
973     if((special_fish & 12) == 12 && fish_settings.explode){
974         load_image_n_scale("sherman/blowup.png", 
975                            &blowup_data,
976                            7, fish_settings.scale);
977
978         ad->special_action|=2;
979     }
980     else
981         blowup_data.pixbuf = NULL;
982
983 }
984
985
986 void fish_exit(void)
987 {
988     int i,j;
989
990     if(scale_diff)
991         j = num_fish;
992     else
993         j = NUMOFFISHTYPES;
994
995     for(i = 0; i < j; i++){
996         if(fish_buffer[i].pixbuf != NULL){
997             g_object_unref(fish_buffer[i].pixbuf);
998
999             if(fish_buffer[i].rev !=NULL)
1000                 g_free(fish_buffer[i].rev);
1001         }
1002     }
1003
1004     
1005     if(blowup_data.pixbuf != NULL){
1006         g_object_unref(blowup_data.pixbuf);
1007
1008         if(blowup_data.rev != NULL)
1009             g_free(blowup_data.rev);
1010
1011     }
1012
1013     if(prey_hunter_data.pixbuf != NULL){
1014         g_object_unref(prey_hunter_data.pixbuf);
1015
1016         if(prey_hunter_data.rev != NULL)
1017             g_free(prey_hunter_data.rev);
1018     }
1019
1020     g_free(fish_buffer);
1021     g_free(fishes);
1022 }
1023
1024