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