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