1 /* $Id: cat-tail.c,v 1.48 2011/08/23 19:44:08 oohara Exp $ */
2 /* [easy] cat tail */
3 
4 #include <stdio.h>
5 /* malloc, rand */
6 #include <stdlib.h>
7 /* strlen, strcmp */
8 #include <string.h>
9 
10 #include "const.h"
11 #include "tenm_object.h"
12 #include "tenm_graphic.h"
13 #include "tenm_primitive.h"
14 #include "util.h"
15 #include "player-shot.h"
16 #include "tenm_table.h"
17 #include "background.h"
18 #include "chain.h"
19 #include "laser.h"
20 #include "normal-shot.h"
21 #include "tenm_math.h"
22 #include "fragment.h"
23 #include "explosion.h"
24 #include "stage-clear.h"
25 #include "score.h"
26 
27 #include "cat-tail.h"
28 
29 #define NEAR_ZERO 0.0001
30 
31 static int cat_tail_move(tenm_object *my, double turn_per_frame);
32 static int cat_tail_hit(tenm_object *my, tenm_object *your);
33 static void cat_tail_second_form(tenm_object *my);
34 static void cat_tail_explode(tenm_object *my);
35 static int cat_tail_signal_turret(tenm_object *my, int n);
36 static int cat_tail_act(tenm_object *my, const tenm_object *player);
37 static int cat_tail_draw(tenm_object *my, int priority);
38 static int cat_tail_green(const tenm_object *my);
39 
40 static tenm_object *cat_tail_turret_new(int what, int index_body,
41                                         int index_turret);
42 static int cat_tail_turret_move(tenm_object *my, double turn_per_frame);
43 static int cat_tail_turret_hit(tenm_object *my, tenm_object *your);
44 static int cat_tail_turret_signal_turret(tenm_object *my, int n);
45 static int cat_tail_turret_signal_body(tenm_object *my, int n);
46 static void cat_tail_turret_explode(tenm_object *my);
47 static int cat_tail_turret_act(tenm_object *my,
48                                const tenm_object *player);
49 static int cat_tail_turret_draw(tenm_object *my, int priority);
50 static int cat_tail_turret_green(const tenm_object *my);
51 
52 static int cat_tail_position(double *result, int mode, int t);
53 
54 tenm_object *
cat_tail_new(void)55 cat_tail_new(void)
56 {
57   int i;
58   tenm_primitive **p = NULL;
59   tenm_object *new = NULL;
60   int *count = NULL;
61   double *count_d = NULL;
62   double result[2];
63   double x;
64   double y;
65 
66   result[0] = 0.0;
67   result[1] = 0.0;
68   cat_tail_position(result, 0, 0);
69   x = result[0];
70   y = result[1];
71 
72   p = (tenm_primitive **) malloc(sizeof(tenm_primitive *) * 3);
73   if (p == NULL)
74   {
75     fprintf(stderr, "cat_tail_new: malloc(p) failed\n");
76     return NULL;
77   }
78 
79   p[0] = (tenm_primitive *) tenm_polygon_new(6,
80                                              x + 48.0, y,
81                                              x + 24.0, y + 41.5692,
82                                              x - 24.0, y + 41.5692,
83                                              x - 48.0, y,
84                                              x - 24.0, y - 41.5692,
85                                              x + 24.0, y - 41.5692);
86   if (p[0] == NULL)
87   {
88     fprintf(stderr, "cat_tail_new: cannot set p[0]\n");
89     free(p);
90     return NULL;
91   }
92   p[1] = (tenm_primitive *) tenm_polygon_new(3,
93                                              x - 24.0, y - 41.5692,
94                                              x - 44.7846, y - 53.5692,
95                                              x - 36.0, y - 20.7846);
96   if (p[1] == NULL)
97   {
98     fprintf(stderr, "cat_tail_new: cannot set p[1]\n");
99     (p[0])->delete(p[0]);
100     free(p);
101     return NULL;
102   }
103   p[2] = (tenm_primitive *) tenm_polygon_new(3,
104                                              x + 24.0, y - 41.5692,
105                                              x + 44.7846, y - 53.5692,
106                                              x + 36.0, y - 20.7846);
107   if (p[2] == NULL)
108   {
109     fprintf(stderr, "cat_tail_new: cannot set p[2]\n");
110     for (i = 0; i < 2; i++)
111       (p[i])->delete(p[i]);
112     free(p);
113     return NULL;
114   }
115 
116   count = (int *) malloc(sizeof(int) * 10);
117   if (count == NULL)
118   {
119     fprintf(stderr, "cat_tail_new: malloc(count) failed\n");
120     for (i = 0; i < 3; i++)
121       (p[i])->delete(p[i]);
122     free(p);
123     return NULL;
124   }
125   count_d = (double *) malloc(sizeof(double) * 2);
126   if (count_d == NULL)
127   {
128     fprintf(stderr, "cat_tail_new: malloc(count_d) failed\n");
129     free(count);
130     for (i = 0; i < 3; i++)
131       (p[i])->delete(p[i]);
132     free(p);
133     return NULL;
134   }
135 
136   /* list of count
137    * [0] for deal_damage
138    * [1] "damaged" timer
139    * [2] move mode
140    * [3] move timer
141    * [4 -- 6] turret index
142    * [7] hand direction
143    * [8] hand theta
144    * [9] "was green when killed" flag
145    */
146   /* list of count_d
147    * [0] speed x
148    * [1] speed y
149    */
150   count[0] = 0;
151   count[1] = 0;
152   count[2] = 0;
153   count[3] = 0;
154   count[4] = -1;
155   count[5] = -1;
156   count[6] = -1;
157   count[7] = -30;
158   count[8] = 0;
159   count[9] = 0;
160 
161   count_d[0] = 0.0;
162   count_d[1] = 0.0;
163 
164   new = tenm_object_new("cat tail", ATTR_BOSS, ATTR_PLAYER_SHOT,
165                         750, x, y,
166                         10, count, 2, count_d, 3, p,
167                         (int (*)(tenm_object *, double))
168                         (&cat_tail_move),
169                         (int (*)(tenm_object *, tenm_object *))
170                         (&cat_tail_hit),
171                         (int (*)(tenm_object *, const tenm_object *))
172                         (&cat_tail_act),
173                         (int (*)(tenm_object *, int))
174                         (&cat_tail_draw));
175   if (new == NULL)
176   {
177     fprintf(stderr, "cat_tail_new: tenm_object_new failed\n");
178     if (count_d != NULL)
179       free(count_d);
180     if (count != NULL)
181       free(count);
182     for (i = 0; i < 3; i++)
183       (p[i])->delete(p[i]);
184     free(p);
185     return NULL;
186   }
187 
188   return new;
189 }
190 
191 static int
cat_tail_move(tenm_object * my,double turn_per_frame)192 cat_tail_move(tenm_object *my, double turn_per_frame)
193 {
194   double dx_temp;
195   double dy_temp;
196 
197   /* sanity check */
198   if (my == NULL)
199   {
200     fprintf(stderr, "cat_tail_move: my is NULL\n");
201     return 0;
202   }
203   if (turn_per_frame <= 0.5)
204   {
205     fprintf(stderr, "cat_tail_move: strange turn_per_frame (%f)\n",
206             turn_per_frame);
207     return 0;
208   }
209 
210   if ((my->count[2] == 2) && (my->count[3] < 0))
211     return 0;
212 
213   dx_temp = my->count_d[0] / turn_per_frame;
214   dy_temp = my->count_d[1] / turn_per_frame;
215   my->x += dx_temp;
216   my->y += dy_temp;
217   if (my->mass != NULL)
218     tenm_move_mass(my->mass, dx_temp, dy_temp);
219 
220   return 0;
221 }
222 
223 static int
cat_tail_hit(tenm_object * my,tenm_object * your)224 cat_tail_hit(tenm_object *my, tenm_object *your)
225 {
226   /* sanity check */
227   if (my == NULL)
228   {
229     fprintf(stderr, "cat_tail_hit: my is NULL\n");
230     return 0;
231   }
232   if (your == NULL)
233   {
234     fprintf(stderr, "cat_tail_hit: your is NULL\n");
235     return 0;
236   }
237 
238   if (!(your->attr & ATTR_PLAYER_SHOT))
239     return 0;
240   if ((my->count[2] != 1) && (my->count[2] != 3))
241     return 0;
242 
243   deal_damage(my, your, 0);
244   if (cat_tail_green(my))
245     add_chain(my, your);
246   my->count[1] = 2;
247 
248   if (my->hit_point <= 0)
249   {
250     set_background(1);
251 
252     if (my->count[2] == 1)
253     {
254       add_score(2250);
255       cat_tail_second_form(my);
256       return 0;
257     }
258     else
259     {
260       add_score(6750);
261       cat_tail_explode(my);
262       return 0;
263     }
264   }
265 
266   return 0;
267 }
268 
269 static void
cat_tail_second_form(tenm_object * my)270 cat_tail_second_form(tenm_object *my)
271 {
272   int i;
273   int n;
274 
275   /* sanity check */
276   if (my == NULL)
277     return;
278 
279   tenm_table_apply_all((int (*)(tenm_object *, int)) (&delete_enemy_shot), 0);
280 
281   for (i = 0; i < 3; i++)
282     if (my->count[4 + i] >= 0)
283       tenm_table_apply(my->count[4 + i],
284                        (int (*)(tenm_object *, int))
285                        (&cat_tail_signal_turret),
286                        0);
287 
288   /* set "was green" flag before we change the life mode */
289   if (cat_tail_green(my))
290   {
291     n = 8;
292     my->count[9] = 1;
293   }
294   else
295   {
296     n = 7;
297     my->count[9] = 0;
298   }
299 
300   tenm_table_add(explosion_new(my->x, my->y - 31.1769,
301                                my->count_d[0] * 0.5,
302                                my->count_d[1] * 0.5,
303                                1, 1000, n, 3.0, 9));
304   tenm_table_add(fragment_new(my->x, my->y - 31.1769,
305                               my->count_d[0] * 0.5, my->count_d[1] * 0.5,
306                               50.0, 20, n, 5.0, 0.0, 20));
307 
308   my->hit_point = 750;
309   my->count[2] = 2;
310   my->count[3] = -30;
311   my->count[1] = 0;
312   my->count_d[0] = (((double) (WINDOW_WIDTH / 2)) - my->x) / 240.0;
313   my->count_d[1] = (((double) (WINDOW_HEIGHT / 4)) - my->y) / 240.0;
314 }
315 
316 static void
cat_tail_explode(tenm_object * my)317 cat_tail_explode(tenm_object *my)
318 {
319   int n;
320   double x;
321   double y;
322   double dx;
323   double dy;
324   int i;
325 
326   /* sanity check */
327   if (my == NULL)
328     return;
329 
330   tenm_table_apply_all((int (*)(tenm_object *, int)) (&delete_enemy_shot), 0);
331 
332   /* set "was green" flag before we change the life mode */
333   if (cat_tail_green(my))
334   {
335     n = 8;
336     my->count[9] = 1;
337   }
338   else
339   {
340     n = 7;
341     my->count[9] = 0;
342   }
343 
344   x = my->x;
345   y = my->y;
346   for (i = 1; i <= 4; i++)
347   {
348     dx = 60.0 * tenm_cos(my->count[7] + my->count[8] * i);
349     dy = 60.0 * tenm_sin(my->count[7] + my->count[8] * i);
350     tenm_table_add(fragment_new(x, y, 0.0, 0.0,
351                                 30.0, 10, n, 4.0, 15.0, 12));
352     tenm_table_add(explosion_new(x + dx / 2.0, y + dy / 2.0, 0.0, 0.0,
353                                  1, 1000, n, 10.0, 9));
354     x += dx;
355     y += dy;
356   }
357   tenm_table_add(explosion_new(my->x, my->y, 0.0, 0.0,
358                                1, 5000, n, 10.0, 6));
359 
360   my->count[2] = 4;
361   my->count[3] = 0;
362   my->count[1] = 0;
363   my->count_d[0] = 0.0;
364   my->count_d[1] = 0.5;
365 
366   /* don't modify my->attr or my->hit_mask here, or the player shot
367    * may fly through the enemy */
368   tenm_mass_delete(my->mass);
369   my->mass = NULL;
370 }
371 
372 static int
cat_tail_signal_turret(tenm_object * my,int n)373 cat_tail_signal_turret(tenm_object *my, int n)
374 {
375   /* sanity check */
376   if (my == NULL)
377     return 0;
378   if (strcmp(my->name, "cat tail turret") != 0)
379     return 0;
380 
381   my->count[2] = 3;
382   /* don't modify my->attr or my->hit_mask here, or the player shot
383    * may fly through the enemy */
384   if (my->mass != NULL)
385   {
386     tenm_mass_delete(my->mass);
387     my->mass = NULL;
388   }
389 
390   return 0;
391 }
392 
393 static int
cat_tail_act(tenm_object * my,const tenm_object * player)394 cat_tail_act(tenm_object *my, const tenm_object *player)
395 {
396   int i;
397   double result[2];
398   double x;
399   double y;
400   double dx;
401   double dy;
402   double length;
403   int theta;
404   double speed;
405 
406   /* sanity check */
407   if (my == NULL)
408   {
409     fprintf(stderr, "cat_tail_act: my is NULL\n");
410     return 0;
411   }
412   if (player == NULL)
413     return 0;
414 
415   /* for deal_damage */
416   my->count[0] = 0;
417 
418   /* "damaged" count down */
419   if (my->count[1] > 0)
420     (my->count[1])--;
421 
422   /* speed change */
423   (my->count[3])++;
424   result[0] = 0.0;
425   result[1] = 0.0;
426   if (my->count[2] <= 1)
427   {
428     cat_tail_position(result, my->count[2], my->count[3]);
429     my->count_d[0] = result[0] - my->x;
430     my->count_d[1] = result[1] - my->y;
431   }
432   else if (my->count[2] == 2)
433   {
434     if (my->count[3] >= 240)
435     {
436       my->count_d[0] = 0.0;
437       my->count_d[1] = 0.0;
438     }
439   }
440   else if (my->count[2] == 3)
441   {
442     if (my->count[3] < 260)
443     {
444       my->count_d[0] = 0.0;
445       my->count_d[1] = 0.0;
446     }
447     else
448     {
449       my->count_d[0] = ((double) (WINDOW_WIDTH / 2))
450         - 100.0 * tenm_sin(my->count[3] - 260);
451       my->count_d[1] = (double) (WINDOW_HEIGHT / 4);
452       my->count_d[0] -= my->x;
453       my->count_d[1] -= my->y;
454     }
455   }
456   else if (my->count[2] == 4)
457   {
458     my->count_d[0] = 0.0;
459     my->count_d[1] = 0.5;
460   }
461   else
462   {
463     my->count_d[0] = 0.0;
464     my->count_d[1] = 0.0;
465   }
466 
467   /* encounter */
468   if (my->count[2] == 0)
469   {
470     if (my->count[3] == 1)
471     {
472       my->count[4] = tenm_table_add(cat_tail_turret_new(0,
473                                                         my->table_index,
474                                                         -1));
475       for (i = 1; i < 3; i++)
476         my->count[4+i]=tenm_table_add(cat_tail_turret_new(i,
477                                                           my->table_index,
478                                                           my->count[4]));
479     }
480 
481     if (my->count[3] >= 120)
482     {
483       my->count[2] = 1;
484       my->count[3] = 0;
485     }
486 
487     return 0;
488   }
489 
490   /* self-destruction */
491   if ((my->count[2] == 1) && (my->count[3] >= 3190))
492   {
493     set_background(2);
494     clear_chain();
495     cat_tail_second_form(my);
496     return 0;
497   }
498   if ((my->count[2] == 3) && (my->count[3] >= 2290))
499   {
500     set_background(2);
501     clear_chain();
502     cat_tail_explode(my);
503     return 0;
504   }
505 
506   /* second form */
507   if (my->count[2] == 2)
508   {
509     if (my->count[3] >= 250)
510     {
511       my->count[2] = 3;
512       my->count[3] = 0;
513     }
514 
515     return 0;
516   }
517 
518   /* dead */
519   if (my->count[2] == 4)
520   {
521     if (cat_tail_green(my))
522       i = 8;
523     else
524       i = 7;
525 
526     if ((my->count[3] >= 30) && (my->count[3] <= 75)
527         && (my->count[3] % 15 == 0))
528     {
529       theta = rand() % 360;
530       tenm_table_add(explosion_new(my->x + 30.0 * tenm_cos(theta),
531                                    my->y + 30.0 * tenm_sin(theta),
532                                    0.0, 0.0,
533                                    2, 300, i, 5.0, 8));
534     }
535 
536     if (my->count[3] > 120)
537     {
538       tenm_table_add(explosion_new(my->x, my->y,
539                                    0.0, 0.0,
540                                    1, 3000, i, 10.0, 8));
541       tenm_table_add(fragment_new(my->x, my->y, 0.0, 0.0,
542                                   30.0, 100, i, 4.0, 0.0, 16));
543       tenm_table_add(fragment_new(my->x, my->y, 0.0, 0.0,
544                                   50.0, 30, i, 2.5, 0.0, 12));
545 
546       tenm_table_add(stage_clear_new(100));
547       return 1;
548     }
549 
550     return 0;
551   }
552 
553   /* move hand */
554   if (my->count[2] == 3)
555   {
556     if (my->count[3] < 120)
557     {
558       my->count[7] += 2;
559       my->count[8] -= 2;
560     }
561     else if (my->count[3] < 150)
562     {
563       ;
564     }
565     else if (my->count[3] < 230)
566     {
567       my->count[7] -= 3;
568       my->count[8] += 3;
569     }
570     else if (my->count[3] < 260)
571     {
572       ;
573     }
574     else
575     {
576       if ((my->count[3] - 260) % 195 < 95)
577       {
578         my->count[7] += 7;
579         my->count[8] -= 7;
580       }
581       else if (((my->count[3] - 260) % 195 >= 100)
582                && ((my->count[3] - 260) % 195 < 190))
583       {
584         my->count[7] -= 7;
585         my->count[8] += 7;
586       }
587     }
588 
589     if (my->count[8] > 0)
590       my->count[8] -= (my->count[8] + 5) / 6;
591     else if (my->count[8] < 0)
592       my->count[8] -= (my->count[8] - 5) / 6;
593   }
594 
595   /* shoot */
596   if (my->count[2] == 1)
597   {
598     if ((my->count[3] >= 600) && (my->count[3] < 1150))
599     {
600       if (my->count[3] % 13 == 0)
601       {
602         tenm_table_add(laser_angle_new(my->x + 40.0 * tenm_sin(my->count[3]),
603                                        my->y,
604                                        5.0, 150 - (my->count[3]%50), 25.0, 3));
605         tenm_table_add(laser_angle_new(my->x + 40.0 * tenm_sin(my->count[3]),
606                                        my->y,
607                                        5.0, 30 + (my->count[3]%50), 25.0, 3));
608       }
609 
610       if ((my->count[5] < 0)
611           && (my->count[3] >= 616) && (my->count[3] <= 1141)
612           && (my->count[3] % 21 == 7))
613       {
614         theta = -30 + 120 * ((my->count[3] % 63) - 7) / 21;
615         dx = player->x - (my->x + 40.0 * tenm_cos(theta));
616         dy = player->y - (my->y + 40.0 * tenm_sin(theta));
617         for (i = 0; i < 360; i += 120)
618           tenm_table_add(normal_shot_point_new(my->x + 40.0 * tenm_cos(-30+i),
619                                                my->y + 40.0 * tenm_sin(-30+i),
620                                                4.0,
621                                                my->x + 40.0 * tenm_cos(-30+i)
622                                                + dx,
623                                                my->y + 40.0 * tenm_sin(-30+i)
624                                                + dy,
625                                                4));
626       }
627     }
628 
629     if ((my->count[3] >= 1350) && (my->count[3] <= 1841))
630     {
631       if ((my->count[3] % 7 == 0))
632       {
633         tenm_table_add(laser_point_new(my->x + 40.0 * tenm_sin(my->count[3]),
634                                        my->y,
635                                        9.0,
636                                        160.0,
637                                        360.0 + 120.0*tenm_sin(my->count[3]*2),
638                                        25.0, 3));
639         tenm_table_add(laser_point_new(my->x + 40.0 * tenm_sin(my->count[3]),
640                                        my->y,
641                                        9.0,
642                                        480.0,
643                                        360.0 + 120.0*tenm_sin(my->count[3]*2),
644                                        25.0, 3));
645       }
646 
647       if ((my->count[6] < 0)
648           && (my->count[3] >= 1365) && (my->count[3] < 1820)
649           && (my->count[3] % 7 == 0))
650       {
651         speed = 4.0 + 0.1 * ((double) (my->count[3] % 35));
652         tenm_table_add(normal_shot_point_new(my->x, my->y,
653                                              speed,
654                                              player->x, player->y,
655                                              4));
656       }
657     }
658 
659     if ((my->count[3] >= 1900) && (my->count[3] < 2420))
660     {
661       if (my->count[3] % 29 == 0)
662       {
663         if (my->count[3] % 58 == 0)
664         {
665           tenm_table_add(laser_angle_new(my->x - 20.0,
666                                          my->y + 20.0,
667                                          4.0, 55, 25.0, 3));
668           tenm_table_add(laser_angle_new(my->x + 20.0,
669                                        my->y + 20.0,
670                                          4.0, 125, 25.0, 3));
671           tenm_table_add(laser_angle_new(my->x - 20.0,
672                                          my->y - 20.0,
673                                          5.5, 35, 25.0, 3));
674           tenm_table_add(laser_angle_new(my->x + 20.0,
675                                          my->y - 20.0,
676                                          5.5, 145, 25.0, 3));
677         }
678         else
679         {
680           tenm_table_add(laser_angle_new(my->x - 20.0,
681                                          my->y + 20.0,
682                                          4.0, 25, 25.0, 3));
683           tenm_table_add(laser_angle_new(my->x + 20.0,
684                                          my->y + 20.0,
685                                          4.0, 155, 25.0, 3));
686           tenm_table_add(laser_angle_new(my->x - 20.0,
687                                          my->y - 20.0,
688                                          5.5, 60, 25.0, 3));
689           tenm_table_add(laser_angle_new(my->x + 20.0,
690                                          my->y - 20.0,
691                                          5.5, 120, 25.0, 3));
692         }
693       }
694 
695       if ((my->count[5] < 0) && (my->count[3] % 20 == 0))
696       {
697         if (my->count[3] % 40 == 0)
698           theta = 30;
699         else
700           theta = 150;
701         dx = player->x - (my->x + 40.0 * tenm_cos(180 - theta));
702         dy = player->y - (my->y + 40.0 * tenm_sin(180 - theta));
703         length = tenm_sqrt((int) (dx * dx + dy * dy));
704         if (length < NEAR_ZERO)
705           length = 1.0;
706         tenm_table_add(normal_shot_point_new(my->x + 40.0 * tenm_cos(30),
707                                              my->y + 40.0 * tenm_sin(30),
708                                              4.0,
709                                              my->x + 40.0 * tenm_cos(30) + dx,
710                                              my->y + 40.0 * tenm_sin(30) + dy,
711                                              4));
712         tenm_table_add(normal_shot_point_new(my->x + 40.0 * tenm_cos(150),
713                                              my->y + 40.0 * tenm_sin(150),
714                                              4.0,
715                                              my->x + 40.0 * tenm_cos(150) + dx,
716                                              my->y + 40.0 * tenm_sin(150) + dy,
717                                              4));
718         tenm_table_add(normal_shot_new(my->x + 40.0 * tenm_cos(-90),
719                                        my->y + 40.0 * tenm_sin(-90),
720                                        4.0 * dx / length
721                                        + 2.0 * (tenm_cos(theta)-tenm_cos(-90)),
722                                        4.0 * dy / length
723                                        + 2.0 * (tenm_sin(theta)-tenm_sin(-90)),
724                                        4, -2, 0));
725       }
726     }
727 
728     if ((my->count[3] >= 2520) && (my->count[3] < 3060))
729     {
730       if (my->count[3] % 7 == 0)
731       {
732         if ((my->count[3] + 270) % 360 < 180)
733         {
734           tenm_table_add(laser_angle_new(my->x - 40.0 * tenm_sin(my->count[3]),
735                                          my->y,
736                                          9.0,
737                                          105 + ((my->count[3]+270) % 360) / 3,
738                                          25.0, 3));
739           tenm_table_add(laser_angle_new(my->x - 40.0 * tenm_sin(my->count[3]),
740                                          my->y,
741                                          9.0,
742                                          15 + ((my->count[3] + 270) % 360) / 3,
743                                          25.0, 3));
744         }
745         else
746         {
747           tenm_table_add(laser_angle_new(my->x - 40.0 * tenm_sin(my->count[3]),
748                                          my->y,
749                                          9.0,
750                                          225 - ((my->count[3]+270) % 360) / 3,
751                                          25.0, 3));
752           tenm_table_add(laser_angle_new(my->x - 40.0 * tenm_sin(my->count[3]),
753                                          my->y,
754                                          9.0,
755                                          135 - ((my->count[3]+270) % 360) / 3,
756                                          25.0, 3));
757         }
758       }
759 
760       if ((my->count[6] < 0) && (my->count[3] % 20 == 0))
761       {
762         for (i = 0; i < 5; i ++)
763           tenm_table_add(normal_shot_point_new(my->x, my->y,
764                                                4.0 + 1.0 * ((double) i),
765                                                player->x, player->y,
766                                                4));
767       }
768     }
769   }
770 
771   if ((my->count[2] == 3) && (my->count[3] % 17 == 0))
772   {
773     x = my->x;
774     y = my->y;
775     for (i = 1; i <= 4; i++)
776     {
777       dx = 60.0 * tenm_cos(my->count[7] + my->count[8] * i);
778       dy = 60.0 * tenm_sin(my->count[7] + my->count[8] * i);
779       x += dx;
780       y += dy;
781       tenm_table_add(laser_point_new(x, y, 6.5 - 0.5 * ((double) i),
782                                      player->x, player->y,
783                                      25.0, 3));
784     }
785   }
786 
787   return 0;
788 }
789 
790 static int
cat_tail_draw(tenm_object * my,int priority)791 cat_tail_draw(tenm_object *my, int priority)
792 {
793   int status = 0;
794   tenm_color color;
795   char temp[32];
796   double x;
797   double y;
798   double dx;
799   double dy;
800   int i;
801   int theta;
802   double length;
803 
804   /* sanity check */
805   if (my == NULL)
806   {
807     fprintf(stderr, "cat_tail_draw: my is NULL\n");
808     return 0;
809   }
810 
811   /* body */
812   /* dead enemy has low priority */
813   if (((my->count[2] <= 3) && (priority == 0))
814       || ((my->count[2] > 3) && (priority == -1)))
815   {
816     if (cat_tail_green(my))
817     {
818       if (my->count[1] >= 1)
819         color = tenm_map_color(109, 125, 9);
820       else
821         color = tenm_map_color(61, 95, 13);
822     }
823     else
824     {
825       if (my->count[1] >= 1)
826         color = tenm_map_color(135, 89, 9);
827       else
828         color = tenm_map_color(95, 47, 13);
829     }
830 
831     if (my->count[2] <= 1)
832     {
833       if (tenm_draw_line((int) (my->x + 36.0), (int) (my->y - 20.7846),
834                          (int) (my->x + 48.0), (int) (my->y),
835                          3, color))
836         status = 1;
837       if (tenm_draw_line((int) (my->x - 36.0), (int) (my->y - 20.7846),
838                          (int) (my->x + 36.0), (int) (my->y - 20.7846),
839                          2, color))
840         status = 1;
841       if (tenm_draw_line((int) (my->x - 48.0), (int) (my->y),
842                          (int) (my->x - 36.0), (int) (my->y - 20.7846),
843                          3, color))
844         status = 1;
845     }
846     else
847     {
848       if (tenm_draw_line((int) (my->x + 24.0), (int) (my->y - 41.5692),
849                          (int) (my->x + 48.0), (int) (my->y),
850                          3, color))
851         status = 1;
852       if (tenm_draw_line((int) (my->x - 48.0), (int) (my->y),
853                          (int) (my->x - 24.0), (int) (my->y - 41.5692),
854                          3, color))
855         status = 1;
856     }
857 
858     if (tenm_draw_line((int) (my->x + 48.0), (int) (my->y),
859                        (int) (my->x + 24.0), (int) (my->y + 41.5692),
860                        3, color))
861       status = 1;
862     if (tenm_draw_line((int) (my->x + 24.0), (int) (my->y + 41.5692),
863                        (int) (my->x - 24.0), (int) (my->y + 41.5692),
864                        3, color))
865       status = 1;
866     if (tenm_draw_line((int) (my->x - 24.0), (int) (my->y + 41.5692),
867                        (int) (my->x - 48.0), (int) (my->y),
868                        3, color))
869       status = 1;
870     if (tenm_draw_line((int) (my->x - 24.0), (int) (my->y - 41.5692),
871                        (int) (my->x + 24.0), (int) (my->y - 41.5692),
872                        2, color))
873       status = 1;
874 
875     if (tenm_draw_line((int) (my->x - 24.0), (int) (my->y - 41.5692),
876                        (int) (my->x - 44.7846), (int) (my->y - 53.5692),
877                        3, color))
878       status = 1;
879     if (tenm_draw_line((int) (my->x - 44.7846), (int) (my->y - 53.5692),
880                        (int) (my->x - 36.0), (int) (my->y - 20.7846),
881                        3, color))
882       status = 1;
883 
884     if (tenm_draw_line((int) (my->x + 24.0), (int) (my->y - 41.5692),
885                        (int) (my->x + 44.7846), (int) (my->y - 53.5692),
886                        3, color))
887       status = 1;
888     if (tenm_draw_line((int) (my->x + 44.7846), (int) (my->y - 53.5692),
889                        (int) (my->x + 36.0), (int) (my->y - 20.7846),
890                        3, color))
891       status = 1;
892 
893     /* hand */
894     if ((my->count[2] == 2) && (my->count[3] > 0))
895     {
896       x = my->x;
897       y = my->y;
898       if (my->count[3] < 0)
899         length = 0.5;
900       else if (my->count[3] < 240)
901         length = ((double) (my->count[3])) * 0.25;
902       else
903         length = 60.0;
904       for (i = 1; i <= 4; i++)
905       {
906         if (my->count[3] < 120)
907           theta = 360;
908         else if (my->count[3] < 240)
909           theta = (120 - my->count[3]) * 3;
910         else
911           theta = 0;
912         dx = length * tenm_cos(my->count[7] + theta * i);
913         dy = length * tenm_sin(my->count[7] + theta * i);
914         if (tenm_draw_line((int) (x), (int) (y),
915                            (int) (x + dx), (int) (y + dy),
916                            1, color))
917           status = 1;
918         if (tenm_draw_circle((int) (x + dx), (int) (y + dy), 5, 1,
919                              tenm_map_color(0, 111, 223)) != 0)
920           status = 1;
921         x += dx;
922         y += dy;
923       }
924     }
925     else if (my->count[2] == 3)
926     {
927       x = my->x;
928       y = my->y;
929       for (i = 1; i <= 4; i++)
930       {
931         dx = 60.0 * tenm_cos(my->count[7] + my->count[8] * i);
932         dy = 60.0 * tenm_sin(my->count[7] + my->count[8] * i);
933         if (tenm_draw_line((int) (x), (int) (y),
934                            (int) (x + dx), (int) (y + dy),
935                            1, color))
936           status = 1;
937         if (tenm_draw_circle((int) (x + dx), (int) (y + dy), 5, 1,
938                              tenm_map_color(0, 111, 223)) != 0)
939           status = 1;
940         x += dx;
941         y += dy;
942       }
943     }
944   }
945 
946   /* hit point stat */
947   if ((priority == 0)
948       && ((my->count[2] == 1) || (my->count[2] == 3)))
949   {
950     sprintf(temp, "%d", my->hit_point);
951     if (draw_string(((int) my->x) - 5, (int) my->y,
952                     temp, (int) strlen(temp)) != 0)
953     {
954       fprintf(stderr, "cat_tail_draw: draw_string failed\n");
955       status = 1;
956     }
957   }
958 
959   return status;
960 }
961 
962 /* return 1 (true) or 0 (false) */
963 static int
cat_tail_green(const tenm_object * my)964 cat_tail_green(const tenm_object *my)
965 {
966   /* sanity check */
967   if (my == NULL)
968     return 0;
969 
970   if ((my->count[2] == 1)
971       && (my->count[3] >= 600) && (my->count[3] < 3160))
972     return 1;
973   if ((my->count[2] == 2)
974       && (my->count[3] < 0) && (my->count[9] != 0))
975     return 1;
976   if ((my->count[2] == 3)
977       && (my->count[3] >= 260) && (my->count[3] <= 2260))
978     return 1;
979   if ((my->count[2] == 4) && (my->count[9] != 0))
980     return 1;
981 
982   return 0;
983 }
984 
985 static tenm_object *
cat_tail_turret_new(int what,int index_body,int index_turret)986 cat_tail_turret_new(int what, int index_body, int index_turret)
987 {
988   int i;
989   tenm_primitive **p = NULL;
990   tenm_object *new = NULL;
991   int *count = NULL;
992   double *count_d = NULL;
993   double result[2];
994   double x;
995   double y;
996 
997   result[0] = 0.0;
998   result[1] = 0.0;
999   cat_tail_position(result, 0, 1);
1000   x = result[0];
1001   y = result[1];
1002 
1003   /* sanity check */
1004   if ((what < 0) || (what > 2))
1005   {
1006     fprintf(stderr, "cat_tail_turret_new: strange what (%d)\n", what);
1007     return NULL;
1008   }
1009 
1010   switch (what)
1011   {
1012   case 0:
1013     x += 180.0;
1014     y += 75.0;
1015     break;
1016   case 1:
1017     x += 180.0;
1018     y += 75.0 + 42.0;
1019     break;
1020   case 2:
1021     x += 180.0;
1022     y += 75.0 - 42.0;
1023     break;
1024   default:
1025     fprintf(stderr, "cat_tail_turret_new: undefined what (%d)\n", what);
1026     break;
1027   }
1028 
1029   p = (tenm_primitive **) malloc(sizeof(tenm_primitive *) * 1);
1030   if (p == NULL)
1031   {
1032     fprintf(stderr, "cat_tail_turret_new: malloc(p) failed\n");
1033     return NULL;
1034   }
1035 
1036   switch (what)
1037   {
1038   case 0:
1039     p[0] = (tenm_primitive *) tenm_polygon_new(4,
1040                                                x + 18.0, y + 24.0,
1041                                                x - 18.0, y + 24.0,
1042                                                x - 18.0, y - 24.0,
1043                                                x + 18.0, y - 24.0);
1044     break;
1045   case 1:
1046     p[0] = (tenm_primitive *) tenm_polygon_new(4,
1047                                                x + 24.0, y + 18.0,
1048                                                x - 24.0, y + 18.0,
1049                                                x - 24.0, y - 18.0,
1050                                                x + 24.0, y - 18.0);
1051     break;
1052   case 2:
1053     p[0] = (tenm_primitive *) tenm_polygon_new(4,
1054                                                x - 24.0, y - 18.0,
1055                                                x + 24.0, y - 18.0,
1056                                                x + 24.0, y + 18.0,
1057                                                x - 24.0, y + 18.0);
1058     break;
1059   default:
1060     fprintf(stderr, "cat_tail_turret_new: undefined what (%d)\n", what);
1061     break;
1062   }
1063 
1064   if (p[0] == NULL)
1065   {
1066     fprintf(stderr, "cat_tail_turret_new: cannot set p[0]\n");
1067     free(p);
1068     return NULL;
1069   }
1070 
1071   count = (int *) malloc(sizeof(int) * 9);
1072   if (count == NULL)
1073   {
1074     fprintf(stderr, "cat_tail_turret_new: malloc(count) failed\n");
1075     for (i = 0; i < 3; i++)
1076       (p[i])->delete(p[i]);
1077     free(p);
1078     return NULL;
1079   }
1080   count_d = (double *) malloc(sizeof(double) * 4);
1081   if (count_d == NULL)
1082   {
1083     fprintf(stderr, "cat_tail_turret_new: malloc(count_d) failed\n");
1084     free(count);
1085     for (i = 0; i < 3; i++)
1086       (p[i])->delete(p[i]);
1087     free(p);
1088     return NULL;
1089   }
1090 
1091   /* list of count
1092    * [0] for deal_damage
1093    * [1] "damaged" timer
1094    * [2] move mode
1095    * [3] move timer
1096    * [4] what
1097    * [5] index body
1098    * [6] index turret center
1099    * [7] number of turret heads dead
1100    * [8] shoot timer
1101    */
1102   /* list of count_d
1103    * [0] speed x
1104    * [1] speed y
1105    * [2] front x
1106    * [3] front y
1107    */
1108   count[0] = 0;
1109   count[1] = 0;
1110   count[2] = 0;
1111   count[3] = 1;
1112   count[4] = what;
1113   count[5] = index_body;
1114   count[6] = index_turret;
1115   count[7] = 0;
1116   count[8] = 0;
1117 
1118   count_d[0] = 0.0;
1119   count_d[1] = 0.0;
1120   switch (what)
1121   {
1122   case 0:
1123     count_d[2] = 0.0;
1124     count_d[3] = 24.0;
1125     break;
1126   case 1:
1127     count_d[2] = 0.0;
1128     count_d[3] = 18.0;
1129     break;
1130   case 2:
1131     count_d[2] = 0.0;
1132     count_d[3] = -18.0;
1133     break;
1134   default:
1135     fprintf(stderr, "cat_tail_turret_new: undefined what (%d)\n", what);
1136     break;
1137   }
1138 
1139   new = tenm_object_new("cat tail turret",
1140                         ATTR_BOSS, ATTR_PLAYER_SHOT,
1141                         750, x, y,
1142                         9, count, 4, count_d, 1, p,
1143                         (int (*)(tenm_object *, double))
1144                         (&cat_tail_turret_move),
1145                         (int (*)(tenm_object *, tenm_object *))
1146                         (&cat_tail_turret_hit),
1147                         (int (*)(tenm_object *, const tenm_object *))
1148                         (&cat_tail_turret_act),
1149                         (int (*)(tenm_object *, int))
1150                         (&cat_tail_turret_draw));
1151   if (new == NULL)
1152   {
1153     fprintf(stderr, "cat_tail_turret_new: tenm_object_new failed\n");
1154     if (count_d != NULL)
1155       free(count_d);
1156     if (count != NULL)
1157       free(count);
1158     for (i = 0; i < 3; i++)
1159       (p[i])->delete(p[i]);
1160     free(p);
1161     return NULL;
1162   }
1163 
1164   return new;
1165 }
1166 
1167 static int
cat_tail_turret_move(tenm_object * my,double turn_per_frame)1168 cat_tail_turret_move(tenm_object *my, double turn_per_frame)
1169 {
1170   double dx_temp;
1171   double dy_temp;
1172 
1173   /* sanity check */
1174   if (my == NULL)
1175   {
1176     fprintf(stderr, "cat_tail_turret_move: my is NULL\n");
1177     return 0;
1178   }
1179   if (turn_per_frame <= 0.5)
1180   {
1181     fprintf(stderr, "cat_tail_turret_move: strange turn_per_frame (%f)\n",
1182             turn_per_frame);
1183     return 0;
1184   }
1185 
1186   dx_temp = my->count_d[0] / turn_per_frame;
1187   dy_temp = my->count_d[1] / turn_per_frame;
1188   my->x += dx_temp;
1189   my->y += dy_temp;
1190   if (my->mass != NULL)
1191     tenm_move_mass(my->mass, dx_temp, dy_temp);
1192 
1193   return 0;
1194 }
1195 
1196 static int
cat_tail_turret_hit(tenm_object * my,tenm_object * your)1197 cat_tail_turret_hit(tenm_object *my, tenm_object *your)
1198 {
1199   /* sanity check */
1200   if (my == NULL)
1201   {
1202     fprintf(stderr, "cat_tail_turret_hit: my is NULL\n");
1203     return 0;
1204   }
1205   if (your == NULL)
1206   {
1207     fprintf(stderr, "cat_tail_turret_hit: your is NULL\n");
1208     return 0;
1209   }
1210 
1211   if (!(your->attr & ATTR_PLAYER_SHOT))
1212     return 0;
1213   if (my->count[2] != 1)
1214     return 0;
1215   if (my->count[4] == 0)
1216     return 0;
1217 
1218   deal_damage(my, your, 0);
1219   if (cat_tail_turret_green(my))
1220     add_chain(my, your);
1221   my->count[1] = 41;
1222 
1223   if (my->hit_point <= 0)
1224   {
1225     add_score(6000);
1226     cat_tail_turret_explode(my);
1227 
1228     tenm_table_apply(my->count[6],
1229                      (int (*)(tenm_object *, int))
1230                      (&cat_tail_turret_signal_turret),
1231                      0);
1232     tenm_table_apply(my->count[5],
1233                      (int (*)(tenm_object *, int))
1234                      (&cat_tail_turret_signal_body),
1235                      my->count[4]);
1236     return 1;
1237   }
1238 
1239   return 0;
1240 }
1241 
1242 static int
cat_tail_turret_signal_turret(tenm_object * my,int n)1243 cat_tail_turret_signal_turret(tenm_object *my, int n)
1244 {
1245   /* sanity check */
1246   if (my == NULL)
1247     return 0;
1248   if (strcmp(my->name, "cat tail turret") != 0)
1249     return 0;
1250 
1251   (my->count[7])++;
1252   if (my->count[7] >= 2)
1253   {
1254     my->count[2] = 2;
1255     /* don't modify my->attr or my->hit_mask here, or the player shot
1256      * may fly through the enemy */
1257     if (my->mass != NULL)
1258     {
1259       tenm_mass_delete(my->mass);
1260       my->mass = NULL;
1261     }
1262   }
1263 
1264   return 0;
1265 }
1266 
1267 static int
cat_tail_turret_signal_body(tenm_object * my,int n)1268 cat_tail_turret_signal_body(tenm_object *my, int n)
1269 {
1270   /* sanity check */
1271   if (my == NULL)
1272     return 0;
1273   if (strcmp(my->name, "cat tail") != 0)
1274     return 0;
1275 
1276   my->count[4 + n] = -1;
1277 
1278   return 0;
1279 }
1280 
1281 static void
cat_tail_turret_explode(tenm_object * my)1282 cat_tail_turret_explode(tenm_object *my)
1283 {
1284   int n;
1285 
1286   /* sanity check */
1287   if (my == NULL)
1288     return;
1289 
1290   if (my->count[4] == 0)
1291     n = 9;
1292   else if (cat_tail_turret_green(my))
1293     n = 8;
1294   else
1295     n = 7;
1296 
1297   tenm_table_add(explosion_new(my->x, my->y,
1298                                my->count_d[0] * 0.5,
1299                                my->count_d[1] * 0.5,
1300                                1, 1000, n, 8.0, 6));
1301   tenm_table_add(fragment_new(my->x, my->y,
1302                               my->count_d[0] * 0.5, my->count_d[1] * 0.5,
1303                               30.0, 30, n, 5.0, 0.0, 20));
1304 }
1305 
1306 static int
cat_tail_turret_act(tenm_object * my,const tenm_object * player)1307 cat_tail_turret_act(tenm_object *my, const tenm_object *player)
1308 {
1309   double result[2];
1310   double temp[2];
1311   double v[2];
1312   double a[2];
1313   double x;
1314   double y;
1315   double temp_x;
1316   double temp_y;
1317   double result_length;
1318   int n;
1319   double length;
1320   int dtheta;
1321   int i;
1322 
1323   /* sanity check */
1324   if (my == NULL)
1325   {
1326     fprintf(stderr, "cat_tail_turret_act: my is NULL\n");
1327     return 0;
1328   }
1329   if (player == NULL)
1330     return 0;
1331 
1332   /* for deal_damage */
1333   my->count[0] = 0;
1334 
1335   /* "damaged" count down */
1336   if (my->count[1] > 0)
1337     (my->count[1])--;
1338 
1339   /* self-destruction */
1340   if (my->count[2] == 3)
1341   {
1342     cat_tail_turret_explode(my);
1343     return 1;
1344   }
1345 
1346   /* aim at the player */
1347   (my->count[3])++;
1348   temp[0] = 0.0;
1349   temp[1] = 0.0;
1350   cat_tail_position(temp, my->count[2], my->count[3]);
1351 
1352   if ((my->count[2] == 0) || (my->count[2] == 2))
1353   {
1354     result[0] = my->count_d[2];
1355     result[1] = my->count_d[3];
1356   }
1357   else
1358   {
1359     v[0] = my->count_d[2];
1360     v[1] = my->count_d[3];
1361     a[0] = player->x - (temp[0] + 180.0);
1362     a[1] = player->y - (temp[1] + 75.0);
1363     if ((my->count[3] < 250)
1364         || ((my->count[3] >= 530) && (my->count[3] < 1200))
1365         || ((my->count[3] >= 1840) && (my->count[3] < 2440)))
1366     {
1367       if (my->count[4] == 2)
1368       {
1369         a[0] *= -1.0;
1370         a[1] *= -1.0;
1371       }
1372     }
1373     else
1374     {
1375       if (my->count[4] != 2)
1376       {
1377         a[0] *= -1.0;
1378         a[1] *= -1.0;
1379       }
1380     }
1381     if (((my->count[3] >= 250) && (my->count[3] < 310))
1382         || ((my->count[3] >= 530) && (my->count[3] < 590))
1383         || ((my->count[3] >= 1200) && (my->count[3] < 1260))
1384         || ((my->count[3] >= 1840) && (my->count[3] < 1900))
1385         || ((my->count[3] >= 2440) && (my->count[3] < 2500)))
1386       dtheta = 3;
1387     else
1388       dtheta = 1;
1389     result[0] = 0.0;
1390     result[1] = 0.0;
1391     vector_rotate_bounded(result, v, a, dtheta);
1392   }
1393 
1394   /* speed change */
1395   result_length = result[0] * result[0] + result[1] * result[1];
1396   result_length = tenm_sqrt((int) result_length);
1397   if ((my->count[4] == 0) || (result_length < NEAR_ZERO))
1398   {
1399     my->count_d[0] = (temp[0] + 180.0) - my->x;
1400     my->count_d[1] = (temp[1] + 75.0) - my->y;
1401   }
1402   else
1403   {
1404     x = result[0] * 42.0 / result_length;
1405     y = result[1] * 42.0 / result_length;
1406     x += temp[0] + 180.0;
1407     y += temp[1] + 75.0;
1408 
1409     my->count_d[0] = x - my->x;
1410     my->count_d[1] = y - my->y;
1411   }
1412 
1413   /* encounter */
1414   if (my->count[2] == 0)
1415   {
1416     if (my->count[3] >= 120)
1417     {
1418       my->count[2] = 1;
1419       my->count[3] = 0;
1420     }
1421     return 0;
1422   }
1423 
1424   /* dead */
1425   if (my->count[2] == 2)
1426   {
1427     my->count_d[0] = 0.0;
1428     my->count_d[1] = 0.5;
1429 
1430     (my->count[8])++;
1431     if ((my->count[8] >= 10) && (my->count[8] <= 55)
1432         && (my->count[8] % 15 == 10))
1433     {
1434       if (my->count[4] == 0)
1435         n = 9;
1436       else if (cat_tail_turret_green(my))
1437         n = 8;
1438       else
1439         n = 7;
1440       tenm_table_add(explosion_new(my->x + ((double) (-30 + (rand() % 61))),
1441                                    my->y + ((double) (-30 + (rand() % 61))),
1442                                    0.0, 0.0,
1443                                    2, 300, n, 5.0, 8));
1444     }
1445 
1446     if (my->count[8] >= 100)
1447       my->count[2] = 3;
1448     return 0;
1449   }
1450 
1451   /* shape change */
1452   my->count_d[2] = result[0];
1453   my->count_d[3] = result[1];
1454 
1455   x = my->count_d[2];
1456   y = my->count_d[3];
1457   temp_x = y;
1458   temp_y = -x;
1459   if (my->count[4] == 0)
1460   {
1461     temp_x *= 3.0 / 4.0;
1462     temp_y *= 3.0 / 4.0;
1463   }
1464   else
1465   {
1466     temp_x *= 4.0 / 3.0;
1467     temp_y *= 4.0 / 3.0;
1468   }
1469 
1470   if (my->mass != NULL)
1471   {
1472     (((tenm_polygon *)(my->mass->p[0]))->v[0])->x = my->x + x + temp_x;
1473     (((tenm_polygon *)(my->mass->p[0]))->v[0])->y = my->y + y + temp_y;
1474     (((tenm_polygon *)(my->mass->p[0]))->v[1])->x = my->x + x - temp_x;
1475     (((tenm_polygon *)(my->mass->p[0]))->v[1])->y = my->y + y - temp_y;
1476     (((tenm_polygon *)(my->mass->p[0]))->v[2])->x = my->x - x - temp_x;
1477     (((tenm_polygon *)(my->mass->p[0]))->v[2])->y = my->y - y - temp_y;
1478     (((tenm_polygon *)(my->mass->p[0]))->v[3])->x = my->x - x + temp_x;
1479     (((tenm_polygon *)(my->mass->p[0]))->v[3])->y = my->y - y + temp_y;
1480   }
1481 
1482   if (my->count[2] != 1)
1483     return 0;
1484 
1485   /* shoot */
1486   length = tenm_sqrt((int) (my->count_d[2] * my->count_d[2]
1487                             + my->count_d[3] * my->count_d[3]));
1488   if (length < NEAR_ZERO)
1489     length = 1.0;
1490 
1491   if ((((my->count[3] >= 70) && (my->count[3] < 200))
1492        || ((my->count[3] >= 600) && (my->count[3] < 1120))
1493        || ((my->count[3] >= 1900) && (my->count[3] < 2420)))
1494       && (my->count[4] == 1) && (my->count[3] % 30 == 10))
1495   {
1496     for (i = 0; i <= 180; i += 30)
1497     {
1498       v[0] = my->count_d[2] / length;
1499       v[1] = my->count_d[3] / length;
1500       result[0] = v[0];
1501       result[1] = v[1];
1502       if (my->count[3] % 60 < 30)
1503         dtheta = 1;
1504       else
1505         dtheta = -1;
1506       vector_rotate(result, v, i * dtheta);
1507       tenm_table_add(normal_shot_new(my->x, my->y,
1508                                      4.0 * my->count_d[2] / length
1509                                      + 2.0 * result[0],
1510                                      4.0 * my->count_d[3] / length
1511                                      + 2.0 * result[1],
1512                                      2, -2, 0));
1513     }
1514   }
1515 
1516   if ((((my->count[3] >= 350) && (my->count[3] < 480))
1517        || ((my->count[3] >= 1300) && (my->count[3] < 1820))
1518        || ((my->count[3] >= 2520) && (my->count[3] < 3040)))
1519       && (my->count[4] == 2) && (my->count[3] % 30 == 20))
1520   {
1521     for (i = -2; i <= 2; i++)
1522     {
1523       tenm_table_add(normal_shot_new(my->x, my->y,
1524                                      4.0 * my->count_d[2] / length
1525                                      + 0.7 * ((double) i),
1526                                      4.0 * my->count_d[3] / length
1527                                      + 0.7 * ((double) i),
1528                                      0, -2, 0));
1529     }
1530     for (i = -2; i <= 2; i++)
1531     {
1532       if (i == 0)
1533         continue;
1534       tenm_table_add(normal_shot_new(my->x, my->y,
1535                                      4.0 * my->count_d[2] / length
1536                                      + 0.7 * ((double) i),
1537                                      4.0 * my->count_d[3] / length
1538                                      + 0.7 * ((double) -i),
1539                                      0, -2, 0));
1540     }
1541   }
1542 
1543   return 0;
1544 }
1545 
1546 static int
cat_tail_turret_draw(tenm_object * my,int priority)1547 cat_tail_turret_draw(tenm_object *my, int priority)
1548 {
1549   int status = 0;
1550   tenm_color color;
1551   char temp[32];
1552   double x;
1553   double y;
1554   double temp_x;
1555   double temp_y;
1556 
1557   /* sanity check */
1558   if (my == NULL)
1559   {
1560     fprintf(stderr, "cat_tail_turret_draw: my is NULL\n");
1561     return 0;
1562   }
1563 
1564   /* dead enemy has low priority */
1565   if (((my->count[2] <= 1) && (priority == 0))
1566       || ((my->count[2] > 1) && (priority == -1)))
1567   {
1568     /* decoration */
1569     if ((my->count[4] == 0) && (my->count[2] <= 1))
1570     {
1571       color = tenm_map_color(182, 123, 162);
1572 
1573       if (tenm_draw_line((int) (my->x), (int) (my->y),
1574                          (int) (my->x - 180.0), (int) (my->y - 75.0),
1575                          1, color))
1576         status = 1;
1577     }
1578 
1579     /* body */
1580     if (my->count[4] == 0)
1581     {
1582       if (my->count[2] > 1)
1583         color = tenm_map_color(182, 123, 162);
1584       else
1585         color = tenm_map_color(95, 13, 68);
1586     }
1587     else if (cat_tail_turret_green(my))
1588     {
1589       if (my->count[1] >= 40)
1590         color = tenm_map_color(109, 125, 9);
1591       else
1592         color = tenm_map_color(61, 95, 13);
1593     }
1594     else
1595     {
1596       if (my->count[1] >= 40)
1597         color = tenm_map_color(135, 89, 9);
1598       else
1599         color = tenm_map_color(95, 47, 13);
1600     }
1601 
1602     x = my->count_d[2];
1603     y = my->count_d[3];
1604     temp_x = y;
1605     temp_y = -x;
1606     if (my->count[4] == 0)
1607     {
1608       temp_x *= 3.0 / 4.0;
1609       temp_y *= 3.0 / 4.0;
1610     }
1611     else
1612     {
1613       temp_x *= 4.0 / 3.0;
1614       temp_y *= 4.0 / 3.0;
1615     }
1616 
1617     if (tenm_draw_line((int) (my->x + x + temp_x), (int) (my->y + y + temp_y),
1618                        (int) (my->x + x - temp_x), (int) (my->y + y - temp_y),
1619                        3, color))
1620       status = 1;
1621     if (tenm_draw_line((int) (my->x + x - temp_x), (int) (my->y + y - temp_y),
1622                        (int) (my->x - x - temp_x), (int) (my->y - y - temp_y),
1623                        3, color))
1624       status = 1;
1625     if (tenm_draw_line((int) (my->x - x - temp_x), (int) (my->y - y - temp_y),
1626                        (int) (my->x - x + temp_x), (int) (my->y - y + temp_y),
1627                        3, color))
1628       status = 1;
1629     if (tenm_draw_line((int) (my->x - x + temp_x), (int) (my->y - y + temp_y),
1630                        (int) (my->x + x + temp_x), (int) (my->y + y + temp_y),
1631                        3, color))
1632       status = 1;
1633   }
1634 
1635   /* hit point stat */
1636   if ((priority == 0) && (my->count[4] != 0) && (my->count[1] > 0))
1637   {
1638     sprintf(temp, "%d", my->hit_point);
1639     if (draw_string(((int) my->x) - 10, (int) my->y,
1640                     temp, (int) strlen(temp)) != 0)
1641     {
1642       fprintf(stderr, "cat_tail_turret_draw: draw_string failed\n");
1643       status = 1;
1644     }
1645   }
1646 
1647   return status;
1648 }
1649 
1650 /* return 1 (true) or 0 (false) */
1651 static int
cat_tail_turret_green(const tenm_object * my)1652 cat_tail_turret_green(const tenm_object *my)
1653 {
1654   /* sanity check */
1655   if (my == NULL)
1656     return 0;
1657 
1658   if (my->count[4] == 0)
1659     return 0;
1660 
1661   if (my->count[2] == 1)
1662   {
1663     if (my->count[3] >= 3160)
1664       return 0;
1665     if ((my->count[3] < 250)
1666         || ((my->count[3] >= 530) && (my->count[3] < 1200))
1667         || ((my->count[3] >= 1840) && (my->count[3] < 2440)))
1668     {
1669       if (my->count[4] == 1)
1670         return 1;
1671     }
1672     else
1673     {
1674       if (my->count[4] == 2)
1675         return 1;
1676     }
1677   }
1678 
1679   return 0;
1680 }
1681 
1682 /* set result (arg 1) to the position of the boss at time t (arg 3)
1683  * result (arg 1) must be double[2] (you must allocate enough memory
1684  * before calling this function)
1685  * return 0 on success, 1 on error
1686  */
1687 static int
cat_tail_position(double * result,int mode,int t)1688 cat_tail_position(double *result, int mode, int t)
1689 {
1690   /* sanity check */
1691   if (result == NULL)
1692   {
1693     fprintf(stderr, "cat_tail_position: result is NULL\n");
1694     return 1;
1695   }
1696   if (t < 0)
1697   {
1698     fprintf(stderr, "cat_tail_position: t is negative (%d)\n", t);
1699     return 1;
1700   }
1701 
1702   if (mode == 0)
1703   {
1704     result[0] = (double) (WINDOW_WIDTH / 2);
1705     result[1] = -150.0
1706       + ((double) (WINDOW_HEIGHT / 4) -  (-150.0)) * ((double) t) / 120.0;
1707   }
1708   else
1709   {
1710     result[0] = (double) (WINDOW_WIDTH / 2) + 100.0 * tenm_sin(t);
1711     result[1] = (double) (WINDOW_HEIGHT / 4);
1712   }
1713 
1714   return 0;
1715 }
1716