Initial push
[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
569     for(i = 0;i < fish_settings.num_fish; i++){
570         aquarium_clean_image((int) fishes[i].tx,
571                              fishes[i].y - ad->viewpoint_start_y,
572                              fishes[i].width, fishes[i].height);
573     }
574
575
576     for(i = 0; i < fish_settings.num_fish; i++){
577         if (fishes[i].frame >= (fishes[i].num_animation - 1)){
578             if(fish_settings.eat){
579                 if(fishes[i].image == &prey_hunter_data){
580                     
581                     //printf("Done eating.Continue.\n");
582                     
583             
584                     /* Left movement is ok. */
585                     /*            else fishes[i].tx-=fishes[i].width-fish_buffer[HUNTER].width;*/
586             
587                     if(!fish_settings.scale_diff){
588                         if(fishes[i].rev) 
589                             fishes[i].tx += fishes[i].width - fish_buffer[HUNTER].width;
590                         fishes[i].width = fish_buffer[HUNTER].width;
591                         fishes[i].height = fish_buffer[HUNTER].height;
592                         fishes[i].image = &fish_buffer[HUNTER];
593                     } else {
594                         if(fishes[i].rev) 
595                             fishes[i].tx += fishes[i].width - fish_buffer[hunter_is].width;
596                         fishes[i].width = fish_buffer[hunter_is].width;
597                         fishes[i].height = fish_buffer[hunter_is].height;
598                         fishes[i].image = &fish_buffer[hunter_is];
599                     }
600
601                     fishes[i].animation = normal_animation;
602                     fishes[i].num_animation = 4;
603                     fishes[i].speed = hunter_speed;
604                     fishes[i].fast_frame_change = 1.0;
605                     fishes[i].frame = 0;
606             
607             
608                 }
609             }
610         
611             if(fish_settings.explode) {
612           
613                 if(fishes[i].image == &blowup_data){
614                     //printf("Done blowing up.\n");
615                     fishes[i].is_dead = TRUE;
616
617                     if(!fish_settings.scale_diff){
618                         fishes[i].width = fish_buffer[BLOWFISH].width;
619                         fishes[i].height = fish_buffer[BLOWFISH].height;
620                         fishes[i].image = &fish_buffer[BLOWFISH];
621                     } else {
622                         fishes[i].width = fish_buffer[blowfish_is].width;
623                         fishes[i].height = fish_buffer[blowfish_is].height;
624                         fishes[i].image = &fish_buffer[blowfish_is];
625                     }
626
627                     fishes[i].animation = normal_animation;
628                     fishes[i].num_animation = 4;
629                     fishes[i].speed = prey_speed;
630                     fishes[i].fast_frame_change = 1.0;
631                     fishes[i].frame = 0;
632
633
634                     /*
635                     fish_settings.num_fish--;
636                     for(k=i;k<fish_settings.num_fish;k++){
637                         fishes[k]=fishes[k+1];
638                         }*/
639
640             
641                 }
642             }
643         }
644     }
645     
646     sel_fish(0, TRUE);
647
648     for (i = 0; i < fish_settings.num_fish; i++) {
649
650         if(fishes[i].is_dead == TRUE){
651
652             if(fish_settings.rebirth){
653                 if(g_rand_int_range(ad->rnd, 0, 100) < 20){
654                     //              printf("Rebirth and salvation..\n");
655                     /* Salvation and rebirth...*/
656                     fishes[i].is_dead = FALSE;
657                     fishes[i].frame = g_rand_int_range(ad->rnd, 0, fishes[i].num_animation);
658
659
660                     if(g_rand_boolean(ad->rnd)){
661                         fishes[i].rev = 1;
662                         fishes[i].travel =
663                             g_rand_int_range(ad->rnd, 0, (ad->virtual_aquarium_x - ad->xmax) / 2) +
664                             fishes[i].width;
665                         fishes[i].tx = -fishes[i].width - fishes[i].travel;
666                     } else {
667                         fishes[i].rev = 0;
668                         fishes[i].travel = 
669                             g_rand_int_range(ad->rnd, 0, (ad->virtual_aquarium_x - ad->xmax) / 2) +
670                             fishes[i].width;
671                         fishes[i].tx = ad->xmax + fishes[i].travel;
672                     }
673                     fishes[i].y = g_rand_int_range(ad->rnd, 0, (ad->virtual_aquarium_y - fishes[i].height));
674
675                     fishes[i].speed_mul = 1.0 + g_rand_double_range(ad->rnd, -15.0 / 100.0, 15.0 / 100.0);
676                 }
677
678             } else {
679                 /* Don't draw zombie fish */
680                 continue;
681             }
682         }
683         
684
685         /* frozen fish doesn't need to be handled, or drawn */
686         if (fishes[i].speed_mul == 0)
687             continue;
688
689         if((fishes[i].type == BDWELLER || fishes[i].type == HAWTHORNE) && !bottom->have_sea_floor)
690             continue;
691
692         /* move fish in horizontal direction, left or right */
693         /* Large aquarium, the fishes are shown more seldom */
694
695         if (!fishes[i].rev) {
696
697             fishes[i].tx -=
698                 (fishes[i].speed[fishes[i].frame]) * (fishes[i].speed_mul * fish_settings.speed / 100);
699
700             if (fishes[i].tx < (-fishes[i].width - fishes[i].travel)) {
701                 /* we moved out of bounds. change direction,
702                  * position, speed. */
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
723             fishes[i].tx +=
724                 (fishes[i].speed[fishes[i].frame]) * (fishes[i].speed_mul * fish_settings.speed / 100);
725
726
727             if (fishes[i].tx > ad->xmax + fishes[i].travel) {
728                 /* we moved out of bounds. change direction,
729                  * position, speed. */
730
731                 fishes[i].travel = g_rand_int_range(ad->rnd, 0, (ad->virtual_aquarium_x - ad->xmax) / 2) +
732                     fishes[i].width;
733                 fishes[i].tx = ad->xmax + fishes[i].travel;
734                 fishes[i].rev = 0;
735
736                 /* If bottom creature, keep the the Y level */
737                 if(fishes[i].type != BDWELLER && fishes[i].type != HAWTHORNE)
738                     fishes[i].y = g_rand_int_range(ad->rnd, 0, ad->virtual_aquarium_y - fishes[i].height);
739
740                 if (ad->proximity)
741                     fishes[i].speed_mul = 0;
742                 else
743                     fishes[i].speed_mul = 1;
744
745             }
746         }
747
748         /* move fish in vertical position randomly by one pixel up or down */
749         /* If the fish last time moved up or down, larger chance that it does that again. */
750
751         j = g_rand_int_range(ad->rnd, 0, 16);
752
753         /* The bottondweller & hawthorne shall be still ;-) */
754         if(fishes[i].type == BDWELLER || fishes[i].type == HAWTHORNE) 
755             j = 0;
756
757         if (((fishes[i].updown == 1) && (j == 6 || j == 7 || j == 8))
758             || j == 8) {
759             fishes[i].y++;
760             fishes[i].updown = 1;
761         } else if (((fishes[i].updown == -1)
762                     && (j == 12 || j == 13 || j == 14)) || j == 12) {
763             fishes[i].y--;
764             fishes[i].updown = -1;
765         } else
766             fishes[i].updown = 0;
767 #ifdef DEBUG
768         /*      printf("\t\t - Calling draw_fish()\n");*/
769 #endif
770             /* animate fishes using fish_animation array */
771             aquarium_draw_image((int) fishes[i].tx,
772                                 fishes[i].y - ad->viewpoint_start_y,
773                                 fishes[i].animation[fishes[i].frame],
774                                 fishes[i].rev, fishes[i].image);
775
776         /* switch to next swimming frame */
777
778
779         fishes[i].delay += fishes[i].speed[fishes[i].frame] * fishes[i].fast_frame_change;
780 #ifdef DEGUG
781         printf("delay:%f speed:%f frame:%d num_ani:%d anipic:%d\n",
782                fishes[i].delay, fishes[i].speed[fishes[i].frame],fishes[i].frame, fishes[i].num_animation, fishes[i].animation[fishes[i].frame]);
783 #endif
784         if (fishes[i].delay >= (7 * fishes[i].speed[fishes[i].frame])) {
785             if (fishes[i].frame >= (fishes[i].num_animation - 1)){
786                 fishes[i].frame = 0;
787             }     
788             else fishes[i].frame ++;
789             fishes[i].delay = 0;
790         }
791
792     }
793 }
794
795 static void fish_flip(SA_Image *this_fish)
796 {
797     int j, k, ypos;
798
799     if(this_fish->image != NULL){
800
801       this_fish->rev = g_malloc0(this_fish->width * 
802                                  this_fish->full_height * 4 );
803     
804       for(j = 0;j < (this_fish->full_height); j++){
805         ypos = j * this_fish->width * 4;
806         for(k = 0; k < this_fish->width; k++){
807           this_fish->rev[ypos + (this_fish->width - k - 1) * 4]     = this_fish->image[ypos + k * 4];
808           this_fish->rev[ypos + (this_fish->width - k - 1) * 4 + 1] = this_fish->image[ypos + k * 4 + 1];
809           this_fish->rev[ypos + (this_fish->width - k - 1) * 4 + 2] = this_fish->image[ypos + k * 4 + 2];
810           this_fish->rev[ypos + (this_fish->width - k - 1) * 4 + 3] = this_fish->image[ypos + k * 4 + 3];
811         }
812       }
813     }
814 }
815
816
817 void fish_turn(void)
818 {
819   int i, m;
820
821
822   if(fish_settings.scale_diff)
823       m = fish_settings.num_fish;
824   else 
825       m = NUMOFFISHTYPES;
826
827   for(i = 0; i < m; i++){
828       fish_flip(&fish_buffer[i]);
829   }
830
831   fish_flip(&blowup_data);
832   fish_flip(&prey_hunter_data);
833
834 }
835
836
837 void fish_init(void)
838 {
839     int i, num_bottom_fish;
840     int type = 0, special_fish = 0;
841
842     Bottom_settings *bottom_settings;
843     
844     bottom_settings = bottom_get_settings_ptr();
845
846     /* Set up this for the rest of the life */
847     ad = aquarium_get_settings_ptr();
848
849     ad->special_action = 0;
850
851
852     /* Save settings for fish_exit() */
853     scale_diff = fish_settings.scale_diff;
854
855     /* 0 - 30 fishes */
856     if(fish_settings.type == RANDOM_POP_FISH)
857         fish_settings.num_fish = g_rand_int_range(ad->rnd, 1, 30);
858
859     num_fish = fish_settings.num_fish;
860
861     if(fish_settings.scale_diff)
862         fish_buffer = g_malloc0(sizeof(SA_Image) * fish_settings.num_fish);
863     else
864         fish_buffer = g_malloc0(sizeof(SA_Image) * NUMOFFISHTYPES);
865
866
867     fishes = g_malloc0(sizeof(Fish) * fish_settings.num_fish);
868
869     num_bottom_fish = bottom_settings->num_bottom_animals;
870
871     if(num_bottom_fish > num_fish)
872         num_bottom_fish = num_fish;
873
874     for (i = 0; i < fish_settings.num_fish; i++) {
875
876         if(fish_settings.type == RANDOM_FISH || fish_settings.type == RANDOM_POP_FISH) {
877
878             /* FIX ME! Bottom dweller and hawthorne chance !*/
879             if((i<num_bottom_fish) && (bottom_settings->have_sea_floor)) {
880
881                 if(g_rand_boolean(ad->rnd)) 
882                     type = BDWELLER;
883                 else type = HAWTHORNE;
884             }
885             else
886                 do{
887                     type = g_rand_int_range(ad->rnd, 0, NUMOFFISHTYPES); 
888                 } while(type == BDWELLER || type == HAWTHORNE);
889         }
890         else{
891             type = sel_fish(i, FALSE);
892         }
893
894
895         if(type == PREY) special_fish |= 1;
896         if(type == HUNTER) special_fish |= 2;
897         if(type == SWORDFISH) special_fish |= 4;
898         if(type == BLOWFISH) special_fish |= 8;
899
900
901         if(!fish_settings.scale_diff){
902
903             if (fish_buffer[type].image == NULL) {
904                 load_image_n_scale(fish_animation[type].file,
905                                    &fish_buffer[type],
906                                    fish_animation[type].pics,
907                                    fish_settings.scale);
908
909             }
910
911             fishes[i].width = fish_buffer[type].width;
912             fishes[i].height = fish_buffer[type].height;
913
914             fishes[i].image = &fish_buffer[type];
915
916         } else {
917
918             if(type != HUNTER && type != BLOWFISH){
919                 load_image_n_scale(fish_animation[type].file, &fish_buffer[i],
920                                    fish_animation[type].pics,
921                                    abs(fish_settings.scale + (g_rand_int_range(ad->rnd, -15, 15)) * fish_settings.scale / 100) );
922             } else {
923                 if(type == HUNTER) hunter_is = i;
924                 if(type == BLOWFISH) blowfish_is = i;
925
926                 load_image_n_scale(fish_animation[type].file, &fish_buffer[i],
927                                    fish_animation[type].pics,
928                                    fish_settings.scale);
929             }
930
931             fishes[i].width = fish_buffer[i].width;
932             fishes[i].height = fish_buffer[i].height;
933
934             fishes[i].image = &fish_buffer[i];
935
936         }
937
938
939         fishes[i].num_animation = fish_animation[type].frames;
940         fishes[i].animation = fish_animation[type].animation;
941
942         fishes[i].speed = fish_animation[type].speed;
943
944
945         fishes[i].type = type;
946         fishes[i].frame = g_rand_int_range(ad->rnd, 0, fishes[i].num_animation);
947
948         fishes[i].rev = g_rand_boolean(ad->rnd);
949         fishes[i].tx = g_rand_int_range(ad->rnd, 0, ad->virtual_aquarium_x - fishes[i].width);
950
951         fishes[i].speed_mul =  1.0 + g_rand_double_range(ad->rnd, -15.0 / 100.0, 15.0 / 100.0);
952
953
954         fishes[i].fast_frame_change = 1.0;
955
956         fishes[i].is_dead = FALSE;
957
958         fishes[i].updown = 0;
959         fishes[i].travel = g_rand_int_range(ad->rnd, 0, (ad->virtual_aquarium_x - ad->xmax) / 2) + fishes[i].width;
960         fishes[i].y = g_rand_int_range(ad->rnd, 0, ad->virtual_aquarium_y - fishes[i].height);
961
962     }
963
964     
965     if((special_fish & 3) == 3 && fish_settings.eat){
966         load_image_n_scale("sherman/eating.png", 
967                            &prey_hunter_data,
968                            7, fish_settings.scale);
969
970         ad->special_action |= 1;
971     } else
972         prey_hunter_data.pixbuf = NULL;
973
974     if((special_fish & 12) == 12 && fish_settings.explode){
975         load_image_n_scale("sherman/blowup.png", 
976                            &blowup_data,
977                            7, fish_settings.scale);
978
979         ad->special_action|=2;
980     }
981     else
982         blowup_data.pixbuf = NULL;
983
984 }
985
986
987 void fish_exit(void)
988 {
989     int i,j;
990
991     if(scale_diff)
992         j = num_fish;
993     else
994         j = NUMOFFISHTYPES;
995
996     for(i = 0; i < j; i++){
997         if(fish_buffer[i].pixbuf != NULL){
998             g_object_unref(fish_buffer[i].pixbuf);
999
1000             if(fish_buffer[i].rev !=NULL)
1001                 g_free(fish_buffer[i].rev);
1002         }
1003     }
1004
1005     
1006     if(blowup_data.pixbuf != NULL){
1007         g_object_unref(blowup_data.pixbuf);
1008
1009         if(blowup_data.rev != NULL)
1010             g_free(blowup_data.rev);
1011
1012     }
1013
1014     if(prey_hunter_data.pixbuf != NULL){
1015         g_object_unref(prey_hunter_data.pixbuf);
1016
1017         if(prey_hunter_data.rev != NULL)
1018             g_free(prey_hunter_data.rev);
1019     }
1020
1021     g_free(fish_buffer);
1022     g_free(fishes);
1023 }
1024
1025