1 /* $Id: last-boss.c,v 1.431 2005/07/12 20:33:12 oohara Exp $ */
2
3 #include <stdio.h>
4 /* malloc, rand */
5 #include <stdlib.h>
6 /* strlen */
7 #include <string.h>
8
9 #include "tenm_object.h"
10 #include "tenm_graphic.h"
11 #include "tenm_primitive.h"
12 #include "const.h"
13 #include "tenm_table.h"
14 #include "laser.h"
15 #include "normal-shot.h"
16 #include "tenm_math.h"
17 #include "util.h"
18 #include "background.h"
19 #include "chain.h"
20 #include "explosion.h"
21 #include "stage-clear.h"
22 #include "score.h"
23 #include "ship.h"
24 /* deal_damage */
25 #include "player-shot.h"
26
27 #include "last-boss.h"
28
29 #define NEAR_ZERO 0.0001
30
31 static int last_boss_hit(tenm_object *my, tenm_object *your);
32 static void last_boss_next(tenm_object *my);
33 static int last_boss_act(tenm_object *my, const tenm_object *player);
34 static int last_boss_act_0(tenm_object *my, const tenm_object *player);
35 static int last_boss_act_1(tenm_object *my, const tenm_object *player);
36 static int last_boss_act_2(tenm_object *my, const tenm_object *player);
37 static int last_boss_act_3(tenm_object *my, const tenm_object *player);
38 static int last_boss_act_4(tenm_object *my, const tenm_object *player);
39 static int last_boss_act_5(tenm_object *my, const tenm_object *player);
40 static int last_boss_draw(tenm_object *my, int priority);
41 static int last_boss_green(const tenm_object *my);
42
43 static tenm_object *last_boss_cage_new(int n);
44 static int last_boss_cage_act(tenm_object *my, const tenm_object *player);
45 static int last_boss_cage_draw(tenm_object *my, int priority);
46
47 static tenm_object *last_boss_star_dust_new(int n);
48 static int last_boss_star_dust_act(tenm_object *my, const tenm_object *player);
49 static int last_boss_star_dust_draw(tenm_object *my, int priority);
50
51 static tenm_object * last_boss_spotlight_new(int n);
52 static int last_boss_spotlight_act(tenm_object *my, const tenm_object *player);
53 static int last_boss_spotlight_draw(tenm_object *my, int priority);
54
55 static tenm_object *last_boss_horizon_circle_new(int n);
56 static int last_boss_horizon_circle_act(tenm_object *my,
57 const tenm_object *player);
58 static int last_boss_horizon_circle_sights(double *result,
59 const double *v1, const double *v2);
60 static int last_boss_horizon_circle_draw(tenm_object *my, int priority);
61
62 static tenm_object *last_boss_horizon_new(double x, double y, int n);
63 static int last_boss_horizon_act(tenm_object *my, const tenm_object *player);
64 static int last_boss_horizon_draw(tenm_object *my, int priority);
65
66 static tenm_object *last_boss_twist_circle_new(int n);
67 static int last_boss_twist_circle_act(tenm_object *my,
68 const tenm_object *player);
69 static int last_boss_twist_circle_draw(tenm_object *my, int priority);
70
71 static tenm_object *last_boss_matrix_new(int n);
72 static int last_boss_matrix_act(tenm_object *my,
73 const tenm_object *player);
74
75 static tenm_object *last_boss_cross_circle_new(int n);
76 static int last_boss_cross_circle_act(tenm_object *my,
77 const tenm_object *player);
78 static int last_boss_cross_circle_draw(tenm_object *my, int priority);
79
80 static tenm_object *last_boss_cross_new(double x, double y, int n);
81 static int last_boss_cross_act(tenm_object *my, const tenm_object *player);
82 static int last_boss_cross_draw(tenm_object *my, int priority);
83
84 tenm_object *
last_boss_new(void)85 last_boss_new(void)
86 {
87 int i;
88 int suffix;
89 tenm_object *new = NULL;
90 int *count = NULL;
91 tenm_primitive **p = NULL;
92 double x = (double) (WINDOW_WIDTH / 2);
93 double y = (double) (WINDOW_HEIGHT / 4);
94
95 p = (tenm_primitive **) malloc(sizeof(tenm_primitive *) * 1);
96 if (p == NULL)
97 {
98 fprintf(stderr, "last_boss_new: malloc(p) failed\n");
99 return NULL;
100 }
101
102 p[0] = (tenm_primitive *) tenm_circle_new(x, y, 60.0);
103 if (p[0] == NULL)
104 {
105 fprintf(stderr, "last_boss_new: cannot set p[0]\n");
106 free(p);
107 return NULL;
108 }
109
110 count = (int *) malloc(sizeof(int) * 19);
111 if (count == NULL)
112 {
113 (p[0])->delete(p[0]);
114 free(p);
115 fprintf(stderr, "last_boss_new: malloc(count) failed\n");
116 return NULL;
117 }
118
119 /* list of count
120 * [0] mode
121 * [1] shoot timer
122 * [2] demo timer
123 * [3] for deal_damage
124 * [4 -- 15] decoration circle management
125 * suffix + 0: center x
126 * suffix + 1: center y
127 * suffix + 2: radius
128 * [16] immutable timer
129 * [17] "damaged" timer
130 * [18] "was green when killed" flag
131 */
132 count[0] = 0;
133 count[1] = 0;
134 count[2] = 0;
135 count[3] = 0;
136 for (i = 0; i < 4; i++)
137 {
138 suffix = i * 3 + 4;
139 if (i == 0)
140 {
141 count[suffix + 0] = WINDOW_WIDTH / 2;
142 count[suffix + 1] = WINDOW_HEIGHT / 4;
143 count[suffix + 2] = -240 + 2;
144 }
145 else
146 {
147 count[suffix + 0] = WINDOW_WIDTH / 2 - 50 + (rand() % 100);
148 count[suffix + 1] = WINDOW_HEIGHT / 4 - 50 + (rand() % 100);
149 count[suffix + 2] = (i - 1) * (-80) + 2;
150 }
151 }
152 count[16] = 0;
153 count[17] = 0;
154 count[18] = 0;
155
156 new = tenm_object_new("L", 0, 0,
157 750, x, y,
158 19, count, 0, NULL, 1, p,
159 (int (*)(tenm_object *, double)) NULL,
160 (int (*)(tenm_object *, tenm_object *))
161 (&last_boss_hit),
162 (int (*)(tenm_object *, const tenm_object *))
163 (&last_boss_act),
164 (int (*)(tenm_object *, int)) (&last_boss_draw));
165 if (new == NULL)
166 {
167 fprintf(stderr, "last_boss_new: tenm_object_new failed\n");
168 if (count != NULL)
169 free(count);
170 (p[0])->delete(p[0]);
171 free(p);
172 return NULL;
173 }
174
175 return new;
176 }
177
178 static int
last_boss_hit(tenm_object * my,tenm_object * your)179 last_boss_hit(tenm_object *my, tenm_object *your)
180 {
181 /* sanity check */
182 if (my == NULL)
183 return 0;
184 if (your == NULL)
185 return 0;
186
187 if (!(your->attr & ATTR_PLAYER_SHOT))
188 return 0;
189 if (my->count[2] >= 0)
190 return 0;
191 if (my->count[16] > 0)
192 return 0;
193
194 deal_damage(my, your, 3);
195 if (last_boss_green(my))
196 add_chain(my, your);
197 my->count[17] = 2;
198
199 if (my->hit_point <= 0)
200 {
201 set_background(1);
202 switch (my->count[0])
203 {
204 case 0:
205 add_score(20000);
206 break;
207 case 1:
208 add_score(30000);
209 break;
210 case 2:
211 add_score(40000);
212 break;
213 case 3:
214 add_score(50000);
215 break;
216 case 4:
217 add_score(60000);
218 break;
219 case 5:
220 add_score(100000);
221 break;
222 default:
223 fprintf(stderr, "last_boss_hit: undefined mode (%d)\n", my->count[0]);
224 break;
225 }
226 last_boss_next(my);
227 return 0;
228 }
229
230 return 0;
231 }
232
233 static void
last_boss_next(tenm_object * my)234 last_boss_next(tenm_object *my)
235 {
236 int n;
237
238 /* sanity check */
239 if (my == NULL)
240 {
241 fprintf(stderr, "last_boss_next: my is NULL\n");
242 return;
243 }
244 tenm_table_apply_all((int (*)(tenm_object *, int)) (&delete_enemy_shot), 0);
245 tenm_table_apply_all((int (*)(tenm_object *, int)) (&delete_enemy), 0);
246
247 /* set "was green" flag before we change the life mode */
248 if (last_boss_green(my))
249 {
250 n = 8;
251 my->count[18] = 1;
252 }
253 else
254 {
255 n = 7;
256 my->count[18] = 0;
257 }
258
259 tenm_table_add(explosion_new(my->x, my->y, 0.0, 0.0,
260 1, 5000, n, 10.0, 6));
261
262 (my->count[0])++;
263 if (my->count[0] == 1)
264 {
265 my->hit_point = 1000;
266 }
267 else if (my->count[0] == 2)
268 {
269 my->hit_point = 600;
270 }
271 else if (my->count[0] == 3)
272 {
273 my->hit_point = 750;
274 }
275 else if (my->count[0] == 4)
276 {
277 my->hit_point = 400;
278 }
279 else if (my->count[0] == 5)
280 {
281 my->hit_point = 1500;
282 }
283 else
284 {
285 /* don't modify my->attr or my->hit_mask here, or the player shot
286 * may fly through the enemy */
287 tenm_mass_delete(my->mass);
288 my->mass = NULL;
289 }
290
291 my->count[1] = 0;
292 my->count[2] = 0;
293 my->count[17] = 0;
294 }
295
296 static int
last_boss_act(tenm_object * my,const tenm_object * player)297 last_boss_act(tenm_object *my, const tenm_object *player)
298 {
299 int i;
300 int suffix;
301 int theta;
302
303 /* sanity check */
304 if (my == NULL)
305 return 0;
306 if (player == NULL)
307 return 0;
308
309 /* for deal_damage */
310 my->count[3] = 0;
311
312 /* "damaged" count down */
313 if (my->count[17] > 0)
314 (my->count[17])--;
315
316 /* encounter */
317 if ((my->count[0] == 0) && (my->count[2] == 210))
318 {
319 my->attr = ATTR_BOSS;
320 my->hit_mask = ATTR_PLAYER_SHOT;
321 }
322
323 /* dead */
324 if (my->count[0] == 6)
325 {
326 my->count[16] = 0;
327 (my->count[1])++;
328 if (last_boss_green(my))
329 i = 8;
330 else
331 i = 7;
332
333 if ((my->count[1] >= 30) && (my->count[1] <= 90)
334 && (my->count[1] % 5 == 0))
335 {
336 theta = rand() % 360;
337 tenm_table_add(explosion_new(my->x + 30.0 * tenm_cos(theta),
338 my->y + 30.0 * tenm_sin(theta),
339 0.0, 0.0,
340 2, 300, i, 5.0, 8));
341 }
342
343 if (my->count[1] == 120)
344 {
345 tenm_table_add(explosion_new(my->x, my->y, 0.0, 0.0,
346 1, 15000, i, 16.0, 15));
347 tenm_table_add(explosion_new(my->x, my->y, 0.0, 0.0,
348 2, 3000, i, 12.0, 15));
349 tenm_table_add(explosion_new(my->x, my->y, 0.0, 0.0,
350 3, 600, i, 9.0, 15));
351
352 tenm_table_add(stage_clear_new(200));
353 return 1;
354 }
355
356 return 0;
357 }
358
359 /* the boss is immutable if the player is immutable */
360 if ((get_ship() < 0) || (player->count[1] > 0))
361 my->count[16] = 100;
362 else if (my->count[16] > 0)
363 (my->count[16])--;
364
365 /* decoration management */
366 for (i = 0; i < 4; i++)
367 {
368 suffix = i * 3 + 4;
369 my->count[suffix + 2] += 2;
370 if (my->count[suffix + 2] > 60)
371 {
372 if (i != 0)
373 {
374 my->count[suffix + 0] = (WINDOW_WIDTH / 2) - 50 + (rand() % 100);
375 my->count[suffix + 1] = (WINDOW_HEIGHT / 4) - 50 + (rand() % 100);
376 }
377 my->count[suffix + 2] = 2;
378 }
379 }
380
381 /* attack */
382 if (my->count[0] == 0)
383 {
384 last_boss_act_0(my, player);
385 }
386 else if (my->count[0] == 1)
387 {
388 last_boss_act_1(my, player);
389 }
390 else if (my->count[0] == 2)
391 {
392 last_boss_act_2(my, player);
393 }
394 else if (my->count[0] == 3)
395 {
396 last_boss_act_3(my, player);
397 }
398 else if (my->count[0] == 4)
399 {
400 last_boss_act_4(my, player);
401 }
402 else if (my->count[0] == 5)
403 {
404 last_boss_act_5(my, player);
405 }
406
407
408 return 0;
409 }
410
411 static int
last_boss_act_0(tenm_object * my,const tenm_object * player)412 last_boss_act_0(tenm_object *my, const tenm_object *player)
413 {
414 /* sanity check */
415 if (my == NULL)
416 return 0;
417 if (player == NULL)
418 return 0;
419
420 if (my->count[2] >= 0)
421 {
422 (my->count[2])++;
423 if ((my->count[2] == 240) || (my->count[2] == 300)
424 || (my->count[2] == 345) || (my->count[2] == 375)
425 || (my->count[2] == 400) || (my->count[2] == 420))
426 tenm_table_add(last_boss_star_dust_new(1));
427 if ((my->count[2] == 440) || (my->count[2] == 460)
428 || (my->count[2] == 480) || (my->count[2] == 500)
429 || (my->count[2] == 520) || (my->count[2] == 540))
430 tenm_table_add(last_boss_star_dust_new(0));
431 if (my->count[2] >= 559)
432 {
433 my->count[1] = 0;
434 my->count[2] = -1;
435 return 0;
436 }
437 return 0;
438 }
439
440 /* self-destruction */
441 (my->count[2])--;
442 if (my->count[2] <= -4030)
443 {
444 set_background(2);
445 clear_chain();
446 last_boss_next(my);
447 return 0;
448 }
449
450 if (my->count[1] == 0)
451 {
452 tenm_table_add(last_boss_star_dust_new(0));
453 }
454
455 tenm_table_add(laser_angle_new(my->x + (double) (-40 + (rand() % 81)),
456 my->y + (double) (-40 + (rand() % 81)),
457 8.5 + ((double) (rand() % 8)) / 4.0,
458 rand() % 360,
459 25.0, 3));
460
461 (my->count[1])++;
462 if (my->count[1] >= 20)
463 my->count[1] = 0;
464
465 return 0;
466 }
467
468 static int
last_boss_act_1(tenm_object * my,const tenm_object * player)469 last_boss_act_1(tenm_object *my, const tenm_object *player)
470 {
471 /* sanity check */
472 if (my == NULL)
473 return 0;
474 if (player == NULL)
475 return 0;
476
477 if (my->count[2] >= 0)
478 {
479 (my->count[2])++;
480 if (my->count[2] == 30)
481 tenm_table_add(last_boss_twist_circle_new(1));
482 if ((my->count[2] == 300) || (my->count[2] == 435))
483 tenm_table_add(last_boss_twist_circle_new(0));
484 if (my->count[2] >= 524)
485 {
486 my->count[1] = 0;
487 my->count[2] = -1;
488 return 0;
489 }
490 return 0;
491 }
492
493 /* self-destruction */
494 (my->count[2])--;
495 if (my->count[2] <= -4030)
496 {
497 set_background(2);
498 clear_chain();
499 last_boss_next(my);
500 return 0;
501 }
502
503 if (my->count[1] == 0)
504 {
505 tenm_table_add(last_boss_twist_circle_new(0));
506 }
507
508 (my->count[1])++;
509 if (my->count[1] >= 90)
510 my->count[1] = 0;
511
512 return 0;
513 }
514
515 static int
last_boss_act_2(tenm_object * my,const tenm_object * player)516 last_boss_act_2(tenm_object *my, const tenm_object *player)
517 {
518 /* sanity check */
519 if (my == NULL)
520 return 0;
521 if (player == NULL)
522 return 0;
523
524 if (my->count[2] >= 0)
525 {
526 (my->count[2])++;
527 if (my->count[2] == 60)
528 tenm_table_add(last_boss_cage_new(1));
529 if (my->count[2] == 240)
530 tenm_table_add(last_boss_cage_new(2));
531 if ((my->count[2] == 390) || (my->count[2] == 510))
532 tenm_table_add(last_boss_cage_new(0));
533
534 if (my->count[2] == 538)
535 tenm_table_add(normal_shot_point_new(my->x, my->y, 9.0,
536 player->x, player->y, 3));
537 if (my->count[2] >= 629)
538 {
539 my->count[1] = 0;
540 my->count[2] = -1;
541 return 0;
542 }
543 return 0;
544 }
545
546 /* self-destruction */
547 (my->count[2])--;
548 if (my->count[2] <= -4030)
549 {
550 set_background(2);
551 clear_chain();
552 last_boss_next(my);
553 return 0;
554 }
555
556 if (my->count[1] == 0)
557 {
558 tenm_table_add(last_boss_cage_new(0));
559 }
560
561 if (my->count[1] % 4 == 0)
562 {
563 tenm_table_add(normal_shot_point_new(my->x, my->y, 9.0,
564 player->x
565 + (double) (-50 + (rand() % 101)),
566 player->y
567 + (double) (-50 + (rand() % 101)),
568 3));
569 }
570
571 (my->count[1])++;
572 if (my->count[1] >= 120)
573 my->count[1] = 0;
574
575 return 0;
576 }
577
578 static int
last_boss_act_3(tenm_object * my,const tenm_object * player)579 last_boss_act_3(tenm_object *my, const tenm_object *player)
580 {
581 /* sanity check */
582 if (my == NULL)
583 return 0;
584 if (player == NULL)
585 return 0;
586
587 if (my->count[2] >= 0)
588 {
589 (my->count[2])++;
590 if (my->count[2] == 30)
591 tenm_table_add(last_boss_spotlight_new(0));
592 if (my->count[2] == 150)
593 tenm_table_add(last_boss_spotlight_new(1));
594 if (my->count[2] == 250)
595 {
596 tenm_table_add(last_boss_spotlight_new(0));
597 tenm_table_add(last_boss_spotlight_new(2));
598 }
599 if (my->count[2] == 330)
600 {
601 tenm_table_add(last_boss_spotlight_new(1));
602 tenm_table_add(last_boss_spotlight_new(3));
603 }
604
605 if (my->count[2] >= 404)
606 {
607 my->count[1] = 0;
608 my->count[2] = -1;
609 return 0;
610 }
611 return 0;
612 }
613
614 /* self-destruction */
615 (my->count[2])--;
616 if (my->count[2] <= -4030)
617 {
618 set_background(2);
619 clear_chain();
620 last_boss_next(my);
621 return 0;
622 }
623
624 if (my->count[1] == 0)
625 {
626 tenm_table_add(last_boss_spotlight_new(0));
627 tenm_table_add(last_boss_spotlight_new(2));
628 }
629 if (my->count[1] == 75)
630 {
631 tenm_table_add(last_boss_spotlight_new(1));
632 tenm_table_add(last_boss_spotlight_new(3));
633 }
634
635 if (my->count[1] % 15 == 0)
636 tenm_table_add(normal_shot_point_new(my->x + (double) (-40 + rand() % 81),
637 my->y + (double) (-40 + rand() % 81),
638 9.0, player->x, player->y, 4));
639
640 (my->count[1])++;
641 if (my->count[1] >= 150)
642 my->count[1] = 0;
643
644 return 0;
645 }
646
647 static int
last_boss_act_4(tenm_object * my,const tenm_object * player)648 last_boss_act_4(tenm_object *my, const tenm_object *player)
649 {
650 /* sanity check */
651 if (my == NULL)
652 return 0;
653 if (player == NULL)
654 return 0;
655
656 if (my->count[2] >= 0)
657 {
658 (my->count[2])++;
659 if (my->count[2] == 30)
660 tenm_table_add(last_boss_horizon_circle_new(1));
661 if (my->count[2] == 240)
662 tenm_table_add(last_boss_horizon_circle_new(2));
663 if (my->count[2] == 420)
664 tenm_table_add(last_boss_horizon_circle_new(0));
665
666 if (my->count[2] >= 569)
667 {
668 my->count[1] = 0;
669 my->count[2] = -1;
670 return 0;
671 }
672 return 0;
673 }
674
675 /* self-destruction */
676 (my->count[2])--;
677 if (my->count[2] <= -4030)
678 {
679 set_background(2);
680 clear_chain();
681 last_boss_next(my);
682 return 0;
683 }
684
685 if (my->count[1] == 0)
686 {
687 tenm_table_add(last_boss_horizon_circle_new(0));
688 }
689
690 if (my->count[1] % 15 == 0)
691 tenm_table_add(laser_point_new(my->x, my->y, 15.0,
692 player->x, player->y,
693 25.0, 0));
694
695 (my->count[1])++;
696 if (my->count[1] >= 150)
697 my->count[1] = 0;
698
699 return 0;
700 }
701
702 static int
last_boss_act_5(tenm_object * my,const tenm_object * player)703 last_boss_act_5(tenm_object *my, const tenm_object *player)
704 {
705 /* sanity check */
706 if (my == NULL)
707 return 0;
708 if (player == NULL)
709 return 0;
710
711 if (my->count[2] >= 0)
712 {
713 (my->count[2])++;
714 if ((my->count[2] == 30) || (my->count[2] == 110)
715 || (my->count[2] == 190) || (my->count[2] == 270)
716 || (my->count[2] == 350) || (my->count[2] == 430)
717 || (my->count[2] == 510) || (my->count[2] == 590))
718 tenm_table_add(last_boss_cross_circle_new(1));
719 if ((my->count[2] == 310) || (my->count[2] == 390)
720 || (my->count[2] == 470) || (my->count[2] == 550))
721 tenm_table_add(last_boss_cross_circle_new(0));
722
723 if (my->count[2] >= 629)
724 {
725 my->count[1] = 0;
726 my->count[2] = -1;
727 return 0;
728 }
729 return 0;
730 }
731
732 /* self-destruction */
733 (my->count[2])--;
734 if (my->count[2] <= -8030)
735 {
736 set_background(2);
737 clear_chain();
738 last_boss_next(my);
739 return 0;
740 }
741
742 if (my->count[1] % 60 == 0)
743 {
744 tenm_table_add(last_boss_matrix_new(0));
745 }
746 if (my->count[1] % 60 == 30)
747 {
748 tenm_table_add(last_boss_matrix_new(1));
749 }
750
751 if (my->count[1] % 80 == 0)
752 {
753 tenm_table_add(last_boss_cross_circle_new(0));
754 }
755 if (my->count[1] % 80 == 40)
756 {
757 tenm_table_add(last_boss_cross_circle_new(1));
758 }
759
760 (my->count[1])++;
761 if (my->count[1] >= 240)
762 my->count[1] = 0;
763
764 return 0;
765 }
766
767 static int
last_boss_draw(tenm_object * my,int priority)768 last_boss_draw(tenm_object *my, int priority)
769 {
770 int i;
771 int r;
772 int width;
773 int suffix;
774 int status = 0;
775 tenm_color color;
776 char temp[32];
777
778 /* sanity check */
779 if (my == NULL)
780 return 0;
781
782 /* decoration */
783 if ((priority == -1) && (my->count[0] < 6))
784 {
785 for (i = 0; i < 4; i++)
786 {
787 suffix = i * 3 + 4;
788
789 if (my->count[suffix + 2] <= 0)
790 continue;
791
792 if (last_boss_green(my))
793 {
794 if (i == 0)
795 color = tenm_map_color(157, 182, 123);
796 else
797 color = tenm_map_color(190, 206, 167);
798 }
799 else
800 {
801 if (i == 0)
802 color = tenm_map_color(182, 148, 123);
803 else
804 color = tenm_map_color(206, 183, 167);
805 }
806
807 if (tenm_draw_circle(my->count[suffix + 0],
808 my->count[suffix + 1],
809 my->count[suffix + 2], 1, color) != 0)
810 status = 1;
811 }
812
813 if ((my->count[16] > 0) && (my->count[16] < 100))
814 {
815 if (last_boss_green(my))
816 color = tenm_map_color(222, 225, 179);
817 else
818 color = tenm_map_color(230, 214, 179);
819
820 if (tenm_draw_circle((int) (my->x), (int) (my->y),
821 60 + my->count[16] * 3, 1, color) != 0)
822 status = 1;
823 }
824 }
825
826 /* body */
827 width = 2;
828
829 if ((my->count[0] == 0) && (my->count[2] >= 0))
830 {
831 if (my->count[2] < 180)
832 {
833 return status;
834 }
835 else if (my->count[2] < 210)
836 {
837 r = 60 + (210 - my->count[2]);
838 width = 1;
839 }
840 else
841 {
842 r = 60;
843 }
844 }
845 else
846 {
847 r = 60;
848 }
849
850 /* dead enemy has low priority */
851 if (((my->count[0] < 6) && (priority == 0))
852 || ((my->count[0] >= 6) && (my->count[1] < 120) && (priority == -1)))
853 {
854 if (last_boss_green(my))
855 {
856 if (my->count[16] > 0)
857 color = tenm_map_color(190, 206, 167);
858 else if (my->count[17] >= 1)
859 color = tenm_map_color(109, 125, 9);
860 else
861 color = tenm_map_color(61, 95, 13);
862 }
863 else
864 {
865 if (my->count[16] > 0)
866 color = tenm_map_color(206, 183, 167);
867 else if (my->count[17] >= 1)
868 color = tenm_map_color(135, 89, 9);
869 else
870 color = tenm_map_color(95, 47, 13);
871 }
872
873
874 if (tenm_draw_circle((int) (my->x), (int) (my->y),
875 r, width, color) != 0)
876 status = 1;
877
878 /* hit point stat */
879 if ((my->count[0] < 6) && (my->count[2] < 0))
880 {
881 sprintf(temp, "%d", my->hit_point);
882 if (draw_string((int) my->x, (int) my->y, temp, (int) strlen(temp)) != 0)
883 {
884 fprintf(stderr, "last_boss_draw: draw_string failed\n");
885 status = 1;
886 }
887 }
888 }
889
890 return status;
891 }
892
893 /* return 1 (true) or 0 (false) */
894 static int
last_boss_green(const tenm_object * my)895 last_boss_green(const tenm_object *my)
896 {
897 /* sanity check */
898 if (my == NULL)
899 return 0;
900
901 if (my->count[0] < 6)
902 {
903 if ((my->count[2] >= 0) && (my->count[2] < 30) && (my->count[18] != 0))
904 return 1;
905 if (my->count[2] >= 0)
906 return 0;
907 if (((my->count[0] < 5) && (my->count[2] <= -4000))
908 || ((my->count[0] >= 5) && (my->count[2] <= -8000)))
909 return 0;
910 return 1;
911 }
912 if ((my->count[0] == 6) && (my->count[18] != 0))
913 return 1;
914
915 return 0;
916 }
917
918 static tenm_object *
last_boss_cage_new(int n)919 last_boss_cage_new(int n)
920 {
921 tenm_object *new = NULL;
922 int *count = NULL;
923
924 /* sanity check */
925 if ((n < 0) || (n > 2))
926 {
927 fprintf(stderr, "last_boss_cage_new: strange n (%d)\n", n);
928 return NULL;
929 }
930
931 count = (int *) malloc(sizeof(int) * 13);
932 if (count == NULL)
933 {
934 fprintf(stderr, "last_boss_cage_new: malloc(count) failed\n");
935 return NULL;
936 }
937
938 /* list of count
939 * [0] color (for delete_enemy_shot)
940 * [1] number of circles
941 * [2] radius
942 * [3 -- 12] center (x, y)
943 */
944 count[0] = 1;
945 if (n == 1)
946 count[1] = 2;
947 else if (n == 2)
948 count[1] = 3;
949 else
950 count[1] = 5;
951 count[2] = 5;
952
953 if (n == 1)
954 {
955 count[3] = rand() % 11 - 5 + (WINDOW_WIDTH / 2);
956 count[4] = rand() % (WINDOW_HEIGHT / 4);
957 count[5] = rand() % 11 - 5 + (WINDOW_WIDTH / 2);
958 count[6] = rand() % (WINDOW_HEIGHT / 4) + (WINDOW_HEIGHT / 2);
959 count[7] = 0.0;
960 count[8] = 0.0;
961 count[9] = 0.0;
962 count[10] = 0.0;
963 count[11] = 0.0;
964 count[12] = 0.0;
965 }
966 else if (n == 2)
967 {
968 count[3] = rand() % (WINDOW_WIDTH / 3);
969 count[4] = rand() % (WINDOW_HEIGHT / 3);
970 count[5] = rand() % (WINDOW_WIDTH / 3) + (WINDOW_WIDTH * 2 / 3);
971 count[6] = rand() % (WINDOW_HEIGHT / 3);
972 count[7] = rand() % 11 - 5 + (WINDOW_WIDTH / 2);
973 count[8] = rand() % (WINDOW_HEIGHT / 3) + (WINDOW_HEIGHT * 2 / 3);
974 count[9] = 0.0;
975 count[10] = 0.0;
976 count[11] = 0.0;
977 count[12] = 0.0;
978 }
979 else
980 {
981 count[3] = rand() % (WINDOW_WIDTH / 3);
982 count[4] = rand() % (WINDOW_HEIGHT / 3);
983 count[5] = rand() % (WINDOW_WIDTH / 3) + (WINDOW_WIDTH * 2 / 3);
984 count[6] = rand() % (WINDOW_HEIGHT / 3);
985 count[7] = rand() % (WINDOW_WIDTH / 3);
986 count[8] = rand() % (WINDOW_HEIGHT / 3) + (WINDOW_HEIGHT * 2 / 3);
987 count[9] = rand() % (WINDOW_WIDTH / 3) + (WINDOW_WIDTH * 2 / 3);
988 count[10] = rand() % (WINDOW_HEIGHT / 3) + (WINDOW_HEIGHT * 2 / 3);
989 count[11] = rand() % (WINDOW_WIDTH / 3) + (WINDOW_WIDTH / 3);
990 count[12] = rand() % (WINDOW_HEIGHT / 3) + (WINDOW_HEIGHT / 3);
991 }
992
993 /* ATTR_ENEMY_SHOT is only to clear it when the player is killed */
994 new = tenm_object_new("L cage", ATTR_ENEMY_SHOT, 0,
995 0,
996 (double) (WINDOW_WIDTH / 2),
997 (double) (WINDOW_HEIGHT / 4),
998 13, count, 0, NULL, 0, NULL,
999 (int (*)(tenm_object *, double)) NULL,
1000 (int (*)(tenm_object *, tenm_object *))
1001 NULL,
1002 (int (*)(tenm_object *, const tenm_object *))
1003 (&last_boss_cage_act),
1004 (int (*)(tenm_object *, int)) (&last_boss_cage_draw));
1005 if (new == NULL)
1006 {
1007 fprintf(stderr, "last_boss_cage_new: tenm_object_new failed\n");
1008 if (count != NULL)
1009 free(count);
1010 return NULL;
1011 }
1012
1013 return new;
1014 }
1015
1016 static int
last_boss_cage_act(tenm_object * my,const tenm_object * player)1017 last_boss_cage_act(tenm_object *my, const tenm_object *player)
1018 {
1019 int i;
1020 int j;
1021 int suffix_i;
1022 int suffix_j;
1023 int dx;
1024 int dy;
1025 int distance_2;
1026 double c;
1027 double x1;
1028 double y1;
1029 double x2;
1030 double y2;
1031
1032 /* sanity check */
1033 if (my == NULL)
1034 return 0;
1035 if (player == NULL)
1036 return 0;
1037
1038 my->count[2] += 5;
1039 if (my->count[2] > 850)
1040 return 1;
1041
1042 if (my->count[2] % 50 != 0)
1043 return 0;
1044
1045 for (i = 0; i < my->count[1]; i++)
1046 for (j = i + 1; j < my->count[1]; j++)
1047 {
1048 suffix_i = 3 + 2 * i;
1049 suffix_j = 3 + 2 * j;
1050 dx = my->count[suffix_i + 0] - my->count[suffix_j + 0];
1051 dy = my->count[suffix_i + 1] - my->count[suffix_j + 1];
1052 distance_2 = dx * dx + dy * dy;
1053 if (my->count[2] * my->count[2] > distance_2 / 4 + 625)
1054 {
1055 /* abuse of distance_2 */
1056 c = tenm_sqrt(my->count[2] * my->count[2] - distance_2 / 4)
1057 / tenm_sqrt(distance_2);
1058 x1 = ((double) (my->count[suffix_i + 0]
1059 + my->count[suffix_j + 0])) / 2.0;
1060 y1 = ((double) (my->count[suffix_i + 1]
1061 + my->count[suffix_j + 1])) / 2.0;
1062 x2 = ((double) -dy) * c;
1063 y2 = ((double) dx) * c;
1064 tenm_table_add(laser_point_new(x1 + x2, y1 + y2, 8.0,
1065 x1 - x2, y1 - y2,
1066 25.0, 1));
1067 tenm_table_add(laser_point_new(x1 - x2, y1 - y2, 8.0,
1068 x1 + x2, y1 + y2,
1069 25.0, 1));
1070 }
1071 }
1072
1073 return 0;
1074 }
1075
1076 static int
last_boss_cage_draw(tenm_object * my,int priority)1077 last_boss_cage_draw(tenm_object *my, int priority)
1078 {
1079 int i;
1080 int suffix;
1081 tenm_color color;
1082 int status = 0;
1083
1084 /* sanity check */
1085 if (my == NULL)
1086 return 0;
1087
1088 if (priority != 0)
1089 return 0;
1090
1091 color = tenm_map_color(99, 158, 138);
1092
1093 for (i = 0; i < my->count[1]; i++)
1094 {
1095 suffix = 3 + 2 * i;
1096 if (tenm_draw_circle(my->count[suffix + 0],
1097 my->count[suffix + 1],
1098 my->count[2],
1099 1, color) != 0)
1100 status = 1;
1101 }
1102
1103 return status;
1104 }
1105
1106 static tenm_object *
last_boss_star_dust_new(int n)1107 last_boss_star_dust_new(int n)
1108 {
1109 tenm_object *new = NULL;
1110 int *count = NULL;
1111 double x;
1112 double y;
1113
1114 /* sanity check */
1115 if ((n < 0) || (n > 2))
1116 {
1117 fprintf(stderr, "last_boss_star_dust_new: strange n (%d)\n", n);
1118 return NULL;
1119 }
1120
1121 count = (int *) malloc(sizeof(int) * 2);
1122 if (count == NULL)
1123 {
1124 fprintf(stderr, "last_boss_star_dust_new: malloc(count) failed\n");
1125 return NULL;
1126 }
1127
1128 x = (double) ((rand() % (WINDOW_WIDTH - 200)) + 100);
1129 if (n == 1)
1130 y = (double) ((rand() % ((WINDOW_HEIGHT - 200) / 2)) + 100);
1131 else
1132 y = (double) ((rand() % (WINDOW_HEIGHT - 200)) + 100);
1133
1134 /* list of count
1135 * [0] color (for delete_enemy_shot)
1136 * [1] shoot timer
1137 */
1138 count[0] = 4;
1139 count[1] = 2;
1140
1141 /* ATTR_ENEMY_SHOT is only to clear it when the player is killed */
1142 new = tenm_object_new("L star dust", ATTR_ENEMY_SHOT, 0,
1143 0, x, y,
1144 2, count, 0, NULL, 0, NULL,
1145 (int (*)(tenm_object *, double)) NULL,
1146 (int (*)(tenm_object *, tenm_object *))
1147 NULL,
1148 (int (*)(tenm_object *, const tenm_object *))
1149 (&last_boss_star_dust_act),
1150 (int (*)(tenm_object *, int))
1151 (&last_boss_star_dust_draw));
1152 if (new == NULL)
1153 {
1154 fprintf(stderr, "last_boss_star_dust_new: tenm_object_new failed\n");
1155 if (count != NULL)
1156 free(count);
1157 return NULL;
1158 }
1159
1160 return new;
1161 }
1162
1163 static int
last_boss_star_dust_act(tenm_object * my,const tenm_object * player)1164 last_boss_star_dust_act(tenm_object *my, const tenm_object *player)
1165 {
1166 int i;
1167 int n;
1168 int theta;
1169 double from_x;
1170 double from_y;
1171 double temp[2];
1172 double result[2];
1173 double speed;
1174
1175 /* sanity check */
1176 if (my == NULL)
1177 return 0;
1178 if (player == NULL)
1179 return 0;
1180
1181 if (my->count[1] > 100)
1182 {
1183 n = rand() % 2;
1184 theta = rand() % 360;
1185 if (rand() % 2 == 0)
1186 speed = 6.0;
1187 else
1188 speed = 4.5;
1189 from_x = my->x + ((double) (my->count[1])) * tenm_cos(theta);
1190 from_y = my->y + ((double) (my->count[1])) * tenm_sin(theta);
1191 temp[0] = player->x - from_x;
1192 temp[1] = player->y - from_y;
1193 if (temp[0] * (my->x - from_x) + temp[1] * (my->y - from_y) < -NEAR_ZERO)
1194 {
1195 theta += 180;
1196 from_x = my->x + ((double) (my->count[1])) * tenm_cos(theta);
1197 from_y = my->y + ((double) (my->count[1])) * tenm_sin(theta);
1198 temp[0] = player->x - from_x;
1199 temp[1] = player->y - from_y;
1200 }
1201
1202 for (i = 0; i < 12; i++)
1203 {
1204 tenm_table_add(normal_shot_point_new(from_x, from_y, speed,
1205 from_x + temp[0],
1206 from_y + temp[1],
1207 4));
1208 if (speed < 5.0)
1209 speed = 6.0;
1210 else
1211 speed = 4.5;
1212
1213 if (n == 0)
1214 theta += 30;
1215 else
1216 theta -= 30;
1217 from_x = my->x + ((double) (my->count[1])) * tenm_cos(theta);
1218 from_y = my->y + ((double) (my->count[1])) * tenm_sin(theta);
1219
1220 result[0] = 1.0;
1221 result[1] = 0.0;
1222 vector_rotate(result, temp, 30);
1223 temp[0] = result[0];
1224 temp[1] = result[1];
1225 }
1226
1227 return 1;
1228 }
1229
1230 (my->count[1])++;
1231
1232 return 0;
1233 }
1234
1235 static int
last_boss_star_dust_draw(tenm_object * my,int priority)1236 last_boss_star_dust_draw(tenm_object *my, int priority)
1237 {
1238 tenm_color color;
1239 int status = 0;
1240
1241 /* sanity check */
1242 if (my == NULL)
1243 return 0;
1244
1245 if (priority != 0)
1246 return 0;
1247
1248 color = tenm_map_color(118, 99, 158);
1249 if (my->count[1] > 0)
1250 if (tenm_draw_circle((int) (my->x), (int) (my->y),
1251 my->count[1], 1, color) != 0)
1252 status = 1;
1253
1254 color = tenm_map_color(158, 158, 158);
1255 if (my->count[1] > 50)
1256 if (tenm_draw_circle((int) (my->x), (int) (my->y),
1257 (my->count[1] - 50) * 2, 1, color) != 0)
1258 status = 1;
1259
1260 return status;
1261 }
1262
1263 static tenm_object *
last_boss_spotlight_new(int n)1264 last_boss_spotlight_new(int n)
1265 {
1266 double x;
1267 double y;
1268 tenm_object *new = NULL;
1269 int *count = NULL;
1270 double *count_d = NULL;
1271
1272 /* sanity check */
1273 if ((n < 0) || (n > 3))
1274 {
1275 fprintf(stderr, "last_boss_spotlight_new: strange n (%d)\n", n);
1276 return NULL;
1277 }
1278
1279 count = (int *) malloc(sizeof(int) * 7);
1280 if (count == NULL)
1281 {
1282 fprintf(stderr, "last_boss_spotlight_new: malloc(count) failed\n");
1283 return NULL;
1284 }
1285
1286 count_d = (double *) malloc(sizeof(double) * 3);
1287 if (count_d == NULL)
1288 {
1289 fprintf(stderr, "last_boss_spotlight_new: malloc(count_d) failed\n");
1290 free(count);
1291 return NULL;
1292 }
1293
1294 /* list of count
1295 * [0] color (for delete_enemy_shot)
1296 * [1] move timer
1297 * [2] shoot timer
1298 * [3] shoot theta
1299 * [4] shoot theta delta
1300 * [5] shoot direction
1301 * [6] mode
1302 */
1303 count[0] = 6;
1304 count[1] = -(rand() % 25);
1305 count[2] = 0;
1306 count[3] = rand() % 360;
1307 if (rand() % 2 == 0)
1308 count[4] = 7;
1309 else
1310 count[4] = -7;
1311 if (rand() % 2 == 0)
1312 count[5] = 90;
1313 else
1314 count[5] = -90;
1315 count[6] = 0;
1316
1317 /* list of count_d
1318 * [0] dx
1319 * [1] dy
1320 * [2] radius
1321 */
1322 if (n == 0)
1323 {
1324 x = 0.0;
1325 y = 0.0;
1326 count_d[0] = 4.8;
1327 count_d[1] = 3.6;
1328 }
1329 else if (n == 1)
1330 {
1331 x = (double) WINDOW_WIDTH;
1332 y = 0.0;
1333 count_d[0] = -4.8;
1334 count_d[1] = 3.6;
1335 }
1336 else if (n == 2)
1337 {
1338 x = (double) WINDOW_WIDTH;
1339 y = (double) WINDOW_HEIGHT;
1340 count_d[0] = -4.8;
1341 count_d[1] = -3.6;
1342 }
1343 else
1344 {
1345 x = 0.0;
1346 y = (double) WINDOW_HEIGHT;
1347 count_d[0] = 4.8;
1348 count_d[1] = -3.6;
1349 }
1350
1351 count_d[2] = 2.5;
1352
1353 /* ATTR_ENEMY_SHOT is only to clear it when the player is killed */
1354 new = tenm_object_new("L spotlight", ATTR_ENEMY_SHOT, 0,
1355 0, x, y,
1356 7, count, 3, count_d, 0, NULL,
1357 (int (*)(tenm_object *, double)) NULL,
1358 (int (*)(tenm_object *, tenm_object *))
1359 NULL,
1360 (int (*)(tenm_object *, const tenm_object *))
1361 (&last_boss_spotlight_act),
1362 (int (*)(tenm_object *, int))
1363 (&last_boss_spotlight_draw));
1364 if (new == NULL)
1365 {
1366 fprintf(stderr, "last_boss_spotlight_new: tenm_object_new failed\n");
1367 if (count_d != NULL)
1368 free(count_d);
1369 if (count != NULL)
1370 free(count);
1371 return NULL;
1372 }
1373
1374 return new;
1375 }
1376
1377 static int
last_boss_spotlight_act(tenm_object * my,const tenm_object * player)1378 last_boss_spotlight_act(tenm_object *my, const tenm_object *player)
1379 {
1380 int i;
1381 int theta;
1382 double dx;
1383 double dy;
1384
1385 /* sanity check */
1386 if (my == NULL)
1387 return 0;
1388 if (player == NULL)
1389 return 0;
1390
1391 /* move */
1392 if (my->count[6] != 1)
1393 {
1394 if (my->count[1] >= 0)
1395 {
1396 /* no need to interpolate */
1397 my->x += my->count_d[0];
1398 my->y += my->count_d[1];
1399 }
1400 if (my->count[6] == 0)
1401 (my->count[1])++;
1402 else
1403 (my->count[1])--;
1404 }
1405
1406 /* shoot */
1407 if (my->count[6] != 0)
1408 {
1409 (my->count[2])++;
1410 if ((my->count[2] >= 0) && (my->count[2] % 12 == 0))
1411 {
1412 for (i = 0; i < 5; i++)
1413 {
1414 theta = my->count[3] + i * 72;
1415 dx = my->count_d[2] * tenm_cos(theta);
1416 dy = my->count_d[2] * tenm_sin(theta);
1417 tenm_table_add(normal_shot_angle_new(my->x + dx, my->y + dy, 6.0,
1418 theta + my->count[5], 0));
1419 }
1420 my->count[3] += my->count[4];
1421 }
1422 }
1423
1424 /* mode change */
1425 if ((my->count[6] == 0) && (my->count[1] >= 0))
1426 {
1427 my->count_d[2] += 2.5;
1428 if (6.0 * ((double) (my->count[1])) > 800.0 + my->count_d[2])
1429 return 1;
1430
1431 dx = player->x - my->x;
1432 dy = player->y - my->y;
1433 if (dx * dx + dy * dy < (my->count_d[2] * my->count_d[2]) - NEAR_ZERO)
1434 {
1435 my->count[6] = 1;
1436 my->count[0] = 0;
1437 my->count[2] = -30;
1438 my->count_d[0] *= -1.0;
1439 my->count_d[1] *= -1.0;
1440 }
1441 }
1442 else if (my->count[6] == 1)
1443 {
1444 /* abuse of shoot timer*/
1445 if (my->count[2] >= 72)
1446 my->count[6] = 2;
1447 }
1448 else if (my->count[6] == 2)
1449 {
1450 my->count_d[2] -= 2.5;
1451 if ((my->count[1] < 0) || (my->count_d[2] < NEAR_ZERO))
1452 return 1;
1453 }
1454
1455 return 0;
1456 }
1457
1458 static int
last_boss_spotlight_draw(tenm_object * my,int priority)1459 last_boss_spotlight_draw(tenm_object *my, int priority)
1460 {
1461 tenm_color color;
1462 int status = 0;
1463
1464 /* sanity check */
1465 if (my == NULL)
1466 return 0;
1467
1468 if (priority != 0)
1469 return 0;
1470
1471 if (my->count[1] < 0)
1472 return 0;
1473
1474 if (my->count[6] == 0)
1475 color = tenm_map_color(158, 158, 158);
1476 else
1477 color = tenm_map_color(0, 191, 47);
1478
1479 if (tenm_draw_circle((int) (my->x), (int) (my->y),
1480 (int) (my->count_d[2]), 1, color) != 0)
1481 status = 1;
1482
1483 return status;
1484 }
1485
1486 static tenm_object *
last_boss_horizon_circle_new(int n)1487 last_boss_horizon_circle_new(int n)
1488 {
1489 int i;
1490 int suffix;
1491 tenm_object *new = NULL;
1492 int *count = NULL;
1493
1494 /* sanity check */
1495 if ((n < 0) || (n > 2))
1496 {
1497 fprintf(stderr, "last_boss_horizon_circle_new: strange n (%d)\n", n);
1498 return NULL;
1499 }
1500
1501 count = (int *) malloc(sizeof(int) * 25);
1502 if (count == NULL)
1503 {
1504 fprintf(stderr, "last_boss_horizon_circle_new: malloc(count) failed\n");
1505 return NULL;
1506 }
1507
1508 /* list of count
1509 * [0] color (for delete_enemy_shot)
1510 * [1] number of circles
1511 * [] circle data
1512 * suffix + 0: radius
1513 * suffix + 1: center theta
1514 * suffix + 2: dr
1515 * suffix + 3: dtheta
1516 * [] circle pair data
1517 * sights in/out at the last frame
1518 * 1: in the window
1519 * 0: out of the window
1520 */
1521 count[0] = 6;
1522
1523 if (n == 1)
1524 {
1525 count[1] = 2;
1526
1527 count[2] = 5;
1528 count[3] = 65;
1529 count[4] = 5;
1530 count[5] = 2;
1531
1532 count[6] = 5;
1533 count[7] = -85;
1534 count[8] = 5;
1535 count[9] = -1;
1536 }
1537 else if (n == 2)
1538 {
1539 count[1] = 3;
1540 for (i = 0; i < 3; i++)
1541 {
1542 suffix = i * 4 + 2;
1543 count[suffix + 0] = rand() % 100 - 110;
1544 count[suffix + 1] = rand() % 360;
1545 count[suffix + 2] = 5;
1546 if (i == 0)
1547 count[suffix + 3] = -2;
1548 else if (i == 1)
1549 count[suffix + 3] = -1;
1550 else if (i == 2)
1551 count[suffix + 3] = 1;
1552 else
1553 count[suffix + 3] = 2;
1554 }
1555 }
1556 else
1557 {
1558 count[1] = 4;
1559 for (i = 0; i < 4; i++)
1560 {
1561 suffix = i * 4 + 2;
1562 count[suffix + 0] = rand() % 100 - 110;
1563 count[suffix + 1] = rand() % 360;
1564 count[suffix + 2] = 5;
1565 if (i == 0)
1566 count[suffix + 3] = -2;
1567 else if (i == 1)
1568 count[suffix + 3] = -1;
1569 else if (i == 2)
1570 count[suffix + 3] = 1;
1571 else
1572 count[suffix + 3] = 2;
1573 }
1574 }
1575
1576 for (i = 18; i <= 24; i++)
1577 count[i] = 1;
1578
1579 /* ATTR_ENEMY_SHOT is only to clear it when the player is killed */
1580 new = tenm_object_new("L horizon circle", ATTR_ENEMY_SHOT, 0,
1581 0,
1582 (double) (WINDOW_WIDTH / 2),
1583 (double) (WINDOW_HEIGHT / 4),
1584 25, count, 0, NULL, 0, NULL,
1585 (int (*)(tenm_object *, double)) NULL,
1586 (int (*)(tenm_object *, tenm_object *))
1587 NULL,
1588 (int (*)(tenm_object *, const tenm_object *))
1589 (&last_boss_horizon_circle_act),
1590 (int (*)(tenm_object *, int))
1591 (&last_boss_horizon_circle_draw));
1592 if (new == NULL)
1593 {
1594 fprintf(stderr, "last_boss_horizon_circle_new: tenm_object_new failed\n");
1595 if (count != NULL)
1596 free(count);
1597 return NULL;
1598 }
1599
1600 return new;
1601 }
1602
1603 static int
last_boss_horizon_circle_act(tenm_object * my,const tenm_object * player)1604 last_boss_horizon_circle_act(tenm_object *my, const tenm_object *player)
1605 {
1606 int i;
1607 int j;
1608 int n;
1609 int suffix;
1610 int dtheta;
1611 int sight_suffix;
1612 int sight_in;
1613 double o_x;
1614 double o_y;
1615 double radius;
1616 double result[2];
1617 double v1[2];
1618 double v2[2];
1619
1620 /* sanity check */
1621 if (my == NULL)
1622 return 0;
1623 if (player == NULL)
1624 return 0;
1625
1626 n = 0;
1627 for (i = 0; i < my->count[1]; i++)
1628 {
1629 suffix = i * 4 + 2;
1630 if ((my->count[suffix + 2] > 0) || (my->count[suffix + 0] >= 5))
1631 {
1632 my->count[suffix + 0] += my->count[suffix + 2];
1633 my->count[suffix + 1] += my->count[suffix + 3];
1634 if (my->count[suffix + 0] > 450)
1635 my->count[suffix + 2] *= -1;
1636 n++;
1637 }
1638 }
1639
1640 if (n <= 0)
1641 return 1;
1642
1643 o_x = (double) WINDOW_WIDTH / 2;
1644 o_y = (double) WINDOW_HEIGHT / 4;
1645
1646 sight_suffix = my->count[1] * 4 + 2;
1647 for (i = 0; i < my->count[1]; i++)
1648 for (j =i + 1; j < my->count[1]; j++)
1649 {
1650 result[0] = 0.0;
1651 result[1] = 0.0;
1652
1653 suffix = i * 4 + 2;
1654 if (my->count[suffix + 0] < 5)
1655 continue;
1656 radius = (double) (my->count[suffix + 0]);
1657 v1[0] = o_x + radius * tenm_cos(my->count[suffix + 1]);
1658 v1[1] = o_y + radius * tenm_sin(my->count[suffix + 1]);
1659 dtheta = my->count[suffix + 1];
1660
1661 suffix = j * 4 + 2;
1662 if (my->count[suffix + 0] < 5)
1663 continue;
1664 radius = (double) (my->count[suffix + 0]);
1665 v2[0] = o_x + radius * tenm_cos(my->count[suffix + 1]);
1666 v2[1] = o_y + radius * tenm_sin(my->count[suffix + 1]);
1667 dtheta -= my->count[suffix + 1];
1668
1669 if (last_boss_horizon_circle_sights(result, v1, v2) == 0)
1670 {
1671 if ((result[0] > NEAR_ZERO)
1672 && (result[0] < ((double) WINDOW_WIDTH) - NEAR_ZERO)
1673 && (result[1] > NEAR_ZERO)
1674 && (result[1] < ((double) WINDOW_HEIGHT) - NEAR_ZERO))
1675 sight_in = 1;
1676 else
1677 sight_in = 0;
1678
1679 if ((my->count[sight_suffix] != sight_in)
1680 && ((dtheta < -2) || (dtheta > 2))
1681 && ((result[0] < 50.0)
1682 || (result[0] > ((double) WINDOW_WIDTH) - 50.0)
1683 || (result[1] < 50.0)
1684 || (result[1] > ((double) WINDOW_HEIGHT) - 50.0)))
1685 {
1686 if ((result[0] * 3.0 >= result[1] * 4.0)
1687 && ((((double) WINDOW_WIDTH) - result[0]) * 3.0
1688 >= result[1] * 4.0))
1689 {
1690 tenm_table_add(last_boss_horizon_new(result[0], -1.0,
1691 0));
1692 }
1693 else if ((result[0] * 3.0
1694 >= (((double) WINDOW_HEIGHT) - result[1]) * 4.0)
1695 && ((((double) WINDOW_WIDTH) - result[0]) * 3.0
1696 >= (((double) WINDOW_HEIGHT) - result[1]) * 4.0))
1697 {
1698 tenm_table_add(last_boss_horizon_new(result[0],
1699 ((double) WINDOW_HEIGHT)+ 1.0,
1700 1));
1701 }
1702 else if ((result[0] * 3.0 < result[1] * 4.0)
1703 && (result[0] * 3.0
1704 < (((double) WINDOW_HEIGHT) - result[1]) * 4.0))
1705 {
1706 tenm_table_add(last_boss_horizon_new(-1.0, result[1],
1707 2));
1708 }
1709 else if (((((double) WINDOW_WIDTH) - result[0]) * 3.0
1710 < result[1] * 4.0)
1711 && ((((double) WINDOW_WIDTH) - result[0]) * 3.0
1712 < (((double) WINDOW_HEIGHT) - result[1]) * 4.0))
1713 {
1714 tenm_table_add(last_boss_horizon_new(((double) WINDOW_WIDTH) + 1.0,
1715 result[1],
1716 3));
1717 }
1718 }
1719
1720 my->count[sight_suffix] = sight_in;
1721 sight_suffix++;
1722 }
1723 }
1724
1725 return 0;
1726 }
1727
1728 /* set result (arg 1) to the other intersection of two circles
1729 * which pass the center of L
1730 * v1 (arg 2) and v2 (arg 3) are the centers of the circles
1731 * all arguments must be double[2] (you must allocate enough memory
1732 * before calling this function)
1733 * return:
1734 * 0 on success
1735 * 1 if there is only one intersection point
1736 * 2 on error
1737 */
1738 static int
last_boss_horizon_circle_sights(double * result,const double * v1,const double * v2)1739 last_boss_horizon_circle_sights(double *result,
1740 const double *v1, const double *v2)
1741 {
1742 double dot;
1743 double length;
1744 double c;
1745 double o_x = (double) (WINDOW_WIDTH / 2);
1746 double o_y = (double) (WINDOW_HEIGHT / 4);
1747
1748 /* sanity check */
1749 if (result == NULL)
1750 {
1751 fprintf(stderr, "last_boss_horizon_circle_sights: result is NULL\n");
1752 return 2;
1753 }
1754 if (v1 == NULL)
1755 {
1756 fprintf(stderr, "last_boss_horizon_circle_sights: v1 is NULL\n");
1757 return 2;
1758 }
1759 if (v2 == NULL)
1760 {
1761 fprintf(stderr, "last_boss_horizon_circle_sights: v2 is NULL\n");
1762 return 2;
1763 }
1764
1765 dot = (o_x - v1[0]) * (v2[0] - v1[0]) + (o_y - v1[1]) * (v2[1] - v1[1]);
1766 length = (v2[0] - v1[0]) * (v2[0] - v1[0]) + (v2[1]-v1[1]) * (v2[1]-v1[1]);
1767 if (length < NEAR_ZERO)
1768 return 1;
1769 c = dot / length;
1770 result[0] = 2.0 * (c * (v2[0] - v1[0]) - (o_x - v1[0])) + o_x;
1771 result[1] = 2.0 * (c * (v2[1] - v1[1]) - (o_y - v1[1])) + o_y;
1772
1773 return 0;
1774 }
1775
1776 static int
last_boss_horizon_circle_draw(tenm_object * my,int priority)1777 last_boss_horizon_circle_draw(tenm_object *my, int priority)
1778 {
1779 int i;
1780 int suffix;
1781 int x;
1782 int y;
1783 double radius;
1784 tenm_color color;
1785 int status = 0;
1786
1787 /* sanity check */
1788 if (my == NULL)
1789 return 0;
1790
1791 if (priority != 0)
1792 return 0;
1793
1794 color = tenm_map_color(158, 158, 158);
1795
1796 for (i = 0; i < my->count[1]; i++)
1797 {
1798 suffix = i * 4 + 2;
1799 if (my->count[suffix + 0] >= 5)
1800 {
1801 radius = (double) (my->count[suffix + 0]);
1802 x = WINDOW_WIDTH / 2 + (int) (radius * tenm_cos(my->count[suffix + 1]));
1803 y = WINDOW_HEIGHT / 4 + (int) (radius * tenm_sin(my->count[suffix + 1]));
1804 if (tenm_draw_circle(x, y, (int) radius, 1, color) != 0)
1805 status = 1;
1806 }
1807 }
1808
1809 return status;
1810 }
1811
1812 static tenm_object *
last_boss_horizon_new(double x,double y,int n)1813 last_boss_horizon_new(double x, double y, int n)
1814 {
1815 tenm_object *new = NULL;
1816 int *count = NULL;
1817
1818 /* sanity check */
1819 if ((n < 0) || (n > 3))
1820 {
1821 fprintf(stderr, "last_boss_horizon_new: strange n (%d)\n", n);
1822 return NULL;
1823 }
1824
1825 count = (int *) malloc(sizeof(int) * 3);
1826 if (count == NULL)
1827 {
1828 fprintf(stderr, "last_boss_horizon_new: malloc(count) failed\n");
1829 return NULL;
1830 }
1831
1832 /* list of count
1833 * [0] color (for delete_enemy_shot)
1834 * [1] n
1835 * [2] shoot timer
1836 */
1837 count[0] = 5;
1838 count[1] = n;
1839 count[2] = 20;
1840
1841 /* ATTR_ENEMY_SHOT is only to clear it when the player is killed */
1842 new = tenm_object_new("L horizon", ATTR_ENEMY_SHOT, 0,
1843 0, x, y,
1844 3, count, 0, NULL, 0, NULL,
1845 (int (*)(tenm_object *, double)) NULL,
1846 (int (*)(tenm_object *, tenm_object *))
1847 NULL,
1848 (int (*)(tenm_object *, const tenm_object *))
1849 (&last_boss_horizon_act),
1850 (int (*)(tenm_object *, int))
1851 (&last_boss_horizon_draw));
1852 if (new == NULL)
1853 {
1854 fprintf(stderr, "last_boss_horizon_new: tenm_object_new failed\n");
1855 if (count != NULL)
1856 free(count);
1857 return NULL;
1858 }
1859
1860 return new;
1861 }
1862
1863 static int
last_boss_horizon_act(tenm_object * my,const tenm_object * player)1864 last_boss_horizon_act(tenm_object *my, const tenm_object *player)
1865 {
1866 /* sanity check */
1867 if (my == NULL)
1868 return 0;
1869 if (player == NULL)
1870 return 0;
1871
1872 (my->count[2])--;
1873 if (my->count[2] <= 0)
1874 {
1875 tenm_table_add(laser_point_new(my->x, my->y, 15.0,
1876 player->x, player->y,
1877 25.0, 1));
1878
1879 if (my->count[1] == 0)
1880 {
1881 tenm_table_add(laser_new(my->x, my->y, 0.0, 0.0,
1882 0.0, 800.0, 5, 7, 0));
1883 }
1884 else if (my->count[1] == 1)
1885 {
1886 tenm_table_add(laser_new(my->x, my->y, 0.0, 0.0,
1887 0.0, -800.0, 5, 7, 0));
1888 }
1889 else if (my->count[1] == 2)
1890 {
1891 tenm_table_add(laser_new(my->x, my->y, 0.0, 0.0,
1892 800.0, 0.0, 5, 7, 0));
1893 }
1894 else if (my->count[1] == 3)
1895 {
1896 tenm_table_add(laser_new(my->x, my->y, 0.0, 0.0,
1897 -800.0, 0.0, 5, 7, 0));
1898 }
1899 else
1900 {
1901 fprintf(stderr, "last_boss_horizon_act: strange my->count[1] (%d)\n",
1902 my->count[1]);
1903 }
1904 return 1;
1905 }
1906
1907 return 0;
1908 }
1909
1910 static int
last_boss_horizon_draw(tenm_object * my,int priority)1911 last_boss_horizon_draw(tenm_object *my, int priority)
1912 {
1913 tenm_color color;
1914 int status = 0;
1915
1916 /* sanity check */
1917 if (my == NULL)
1918 return 0;
1919
1920 if (priority != 0)
1921 return 0;
1922
1923 if (my->count[2] <= 0)
1924 return 1;
1925
1926 color = tenm_map_color(175, 0, 239);
1927 if (tenm_draw_circle((int) (my->x), (int) (my->y),
1928 my->count[2] * 6, 1, color) != 0)
1929 status = 1;
1930
1931 /*
1932 color = tenm_map_color(142, 99, 158);
1933 if (my->count[1] == 0)
1934 {
1935 if (tenm_draw_line((int) (my->x), (int) (my->y),
1936 (int) (my->x), (int) (my->y + 800.0),
1937 1, color) != 0)
1938 status = 1;
1939 }
1940 else if (my->count[1] == 1)
1941 {
1942 if (tenm_draw_line((int) (my->x), (int) (my->y),
1943 (int) (my->x), (int) (my->y - 800.0),
1944 1, color) != 0)
1945 status = 1;
1946 }
1947 else if (my->count[1] == 2)
1948 {
1949 if (tenm_draw_line((int) (my->x), (int) (my->y),
1950 (int) (my->x + 800.0), (int) (my->y),
1951 1, color) != 0)
1952 status = 1;
1953 }
1954 else if (my->count[1] == 3)
1955 {
1956 if (tenm_draw_line((int) (my->x), (int) (my->y),
1957 (int) (my->x - 800.0), (int) (my->y),
1958 1, color) != 0)
1959 status = 1;
1960 }
1961 else
1962 {
1963 fprintf(stderr, "last_boss_horizon_draw: strange my->count[1] (%d)\n",
1964 my->count[1]);
1965 }
1966 */
1967
1968 return status;
1969 }
1970
1971 static tenm_object *
last_boss_twist_circle_new(int n)1972 last_boss_twist_circle_new(int n)
1973 {
1974 double x;
1975 double y;
1976 tenm_object *new = NULL;
1977 int *count = NULL;
1978
1979 /* sanity check */
1980 if ((n < 0) || (n > 1))
1981 {
1982 fprintf(stderr, "last_boss_twist_circle_new: strange n (%d)\n", n);
1983 return NULL;
1984 }
1985
1986 count = (int *) malloc(sizeof(int) * 8);
1987 if (count == NULL)
1988 {
1989 fprintf(stderr, "last_boss_twist_circle_new: malloc(count) failed\n");
1990 return NULL;
1991 }
1992
1993 if (n == 1)
1994 {
1995 x = (double) ((WINDOW_WIDTH / 2) - 5 + (rand() % 11));
1996 y = (double) ((WINDOW_HEIGHT / 2) - 5 + (rand() % 11));
1997 }
1998 else
1999 {
2000 x = (double) ((WINDOW_WIDTH / 3) + (rand() % (WINDOW_WIDTH / 3)));
2001 y = (double) ((WINDOW_HEIGHT / 3) + (rand() % (WINDOW_HEIGHT / 3)));
2002 }
2003
2004 /* list of count
2005 * [0] color (for delete_enemy_shot)
2006 * [1] dtheta total
2007 * [2] appear timer
2008 * [3] radius of the small circle
2009 * [4] radius ratio
2010 * [5] theta of the small circle
2011 * [6] theta of the laser
2012 * [7] dtheta of the small circle
2013 */
2014 count[0] = 6;
2015 count[1] = 0;
2016 count[2] = 49;
2017 count[3] = 50;
2018 count[4] = 6;
2019 if (n == 1)
2020 {
2021 count[5] = -95 - rand() % 11;
2022 count[6] = 185 + rand() % 11;
2023 count[7] = -3;
2024 }
2025 else
2026 {
2027 count[5] = rand() % 360;
2028 count[6] = rand() % 360;
2029 if (rand() % 2 == 0)
2030 count[7] = 3;
2031 else
2032 count[7] = -3;
2033 }
2034
2035 /* ATTR_ENEMY_SHOT is only to clear it when the player is killed */
2036 new = tenm_object_new("L twist circle", ATTR_ENEMY_SHOT, 0,
2037 0, x, y,
2038 8, count, 0, NULL, 0, NULL,
2039 (int (*)(tenm_object *, double)) NULL,
2040 (int (*)(tenm_object *, tenm_object *))
2041 NULL,
2042 (int (*)(tenm_object *, const tenm_object *))
2043 (&last_boss_twist_circle_act),
2044 (int (*)(tenm_object *, int))
2045 (&last_boss_twist_circle_draw));
2046 if (new == NULL)
2047 {
2048 fprintf(stderr, "last_boss_twist_circle_new: tenm_object_new failed\n");
2049 if (count != NULL)
2050 free(count);
2051 return NULL;
2052 }
2053
2054 return new;
2055 }
2056
2057 static int
last_boss_twist_circle_act(tenm_object * my,const tenm_object * player)2058 last_boss_twist_circle_act(tenm_object *my, const tenm_object *player)
2059 {
2060 double temp;
2061 double x;
2062 double y;
2063
2064 /* sanity check */
2065 if (my == NULL)
2066 return 0;
2067 if (player == NULL)
2068 return 0;
2069
2070 if (my->count[2] > 0)
2071 {
2072 (my->count[2])--;
2073 return 0;
2074 }
2075
2076 my->count[5] += my->count[7];
2077 my->count[6] += (-1) * my->count[7] * my->count[4];
2078
2079 my->count[1] += my->count[7];
2080 if ((my->count[1] < -720) || (my->count[1] > 720))
2081 return 1;
2082
2083 temp = (double) (my->count[3] * (my->count[4] - 1));
2084 x = my->x + temp * tenm_cos(my->count[5]);
2085 y = my->y + temp * tenm_sin(my->count[5]);
2086
2087 if ((my->count[1] < -360) || (my->count[1] > 360))
2088 {
2089 my->count[0] = 0;
2090 if (my->count[1] % (my->count[7] * 20) != 0)
2091 return 0;
2092 tenm_table_add(laser_point_new(x, y, 3.0,
2093 player->x, player->y,
2094 (double) (my->count[3]), 0));
2095 }
2096 else
2097 {
2098 my->count[0] = 2;
2099 if (my->count[1] % (my->count[7] * 2) != 0)
2100 return 0;
2101 tenm_table_add(laser_angle_new(x, y, 3.0, my->count[6],
2102 (double) (my->count[3]), 2));
2103 }
2104
2105 return 0;
2106 }
2107
2108 static int
last_boss_twist_circle_draw(tenm_object * my,int priority)2109 last_boss_twist_circle_draw(tenm_object *my, int priority)
2110 {
2111 int x;
2112 int y;
2113 double temp;
2114 tenm_color color;
2115 int status = 0;
2116
2117 /* sanity check */
2118 if (my == NULL)
2119 return 0;
2120
2121 if (priority != 0)
2122 return 0;
2123
2124 if (my->count[2] > 0)
2125 {
2126 color = tenm_map_color(158, 158, 158);
2127 if (tenm_draw_circle((int) (my->x), (int) (my->y),
2128 (my->count[3] - my->count[2]) * my->count[4],
2129 1, color) != 0)
2130 status = 1;
2131
2132 if ((my->count[3] - my->count[2]) * my->count[4] > my->count[3])
2133 {
2134 temp = (double) ((my->count[3] - my->count[2]) * my->count[4]
2135 - my->count[3]);
2136 x = (int) (my->x + temp * tenm_cos(my->count[5]));
2137 y = (int) (my->y + temp * tenm_sin(my->count[5]));
2138 if (tenm_draw_circle(x, y, my->count[3], 1, color) != 0)
2139 status = 1;
2140 }
2141 }
2142 else
2143 {
2144 if ((my->count[1] < -360) || (my->count[1] > 360))
2145 color = tenm_map_color(99, 158, 114);
2146 else
2147 color = tenm_map_color(99, 143, 158);
2148
2149 if (tenm_draw_circle((int) (my->x), (int) (my->y),
2150 my->count[3] * my->count[4], 1, color) != 0)
2151 status = 1;
2152
2153 temp = (double) (my->count[3] * (my->count[4] - 1));
2154 x = (int) (my->x + temp * tenm_cos(my->count[5]));
2155 y = (int) (my->y + temp * tenm_sin(my->count[5]));
2156 if (tenm_draw_circle(x, y, my->count[3], 1, color) != 0)
2157 status = 1;
2158 }
2159
2160 return status;
2161 }
2162
2163 static tenm_object *
last_boss_matrix_new(int n)2164 last_boss_matrix_new(int n)
2165 {
2166 double x;
2167 tenm_object *new = NULL;
2168 int *count = NULL;
2169
2170 /* sanity check */
2171 if ((n < 0) || (n > 1))
2172 {
2173 fprintf(stderr, "last_boss_matrix_new: strange n (%d)\n", n);
2174 return NULL;
2175 }
2176
2177 count = (int *) malloc(sizeof(int) * 3);
2178 if (count == NULL)
2179 {
2180 fprintf(stderr, "last_boss_matrix_new: malloc(count) failed\n");
2181 return NULL;
2182 }
2183
2184 if (n == 0)
2185 x = 0.0;
2186 else
2187 x = (double) (WINDOW_WIDTH);
2188
2189 /* list of count
2190 * [0] color (for delete_enemy_shot)
2191 * [1] n
2192 * [2] shoot timer
2193 */
2194 count[0] = 3;
2195 count[1] = n;
2196 count[2] = rand() % 15;
2197
2198 /* ATTR_ENEMY_SHOT is only to clear it when the player is killed */
2199 new = tenm_object_new("L matrix", ATTR_ENEMY_SHOT, 0,
2200 0, x, 0.0,
2201 3, count, 0, NULL, 0, NULL,
2202 (int (*)(tenm_object *, double)) NULL,
2203 (int (*)(tenm_object *, tenm_object *))
2204 NULL,
2205 (int (*)(tenm_object *, const tenm_object *))
2206 (&last_boss_matrix_act),
2207 (int (*)(tenm_object *, int)) NULL);
2208 if (new == NULL)
2209 {
2210 fprintf(stderr, "last_boss_matrix_new: tenm_object_new failed\n");
2211 if (count != NULL)
2212 free(count);
2213 return NULL;
2214 }
2215
2216 return new;
2217 }
2218
2219 static int
last_boss_matrix_act(tenm_object * my,const tenm_object * player)2220 last_boss_matrix_act(tenm_object *my, const tenm_object *player)
2221 {
2222 double speed;
2223 double dx;
2224
2225 /* sanity check */
2226 if (my == NULL)
2227 return 0;
2228 if (player == NULL)
2229 return 0;
2230
2231 /* no need to interpolate */
2232 if (my->count[1] == 0)
2233 {
2234 my->x += 4.5;
2235 if (my->x > (double) (WINDOW_WIDTH + WINDOW_HEIGHT))
2236 return 1;
2237 }
2238 else
2239 {
2240 my->x -= 4.5;
2241 if (my->x < (double) -WINDOW_HEIGHT)
2242 return 1;
2243 }
2244
2245 (my->count[2])++;
2246 if (my->count[2] % 3 == 0)
2247 {
2248
2249 if (my->count[2] == 3)
2250 speed = 6.0;
2251 else if (my->count[2] == 6)
2252 speed = 9.0;
2253 else if (my->count[2] == 9)
2254 speed = 12.0;
2255 else if (my->count[2] == 12)
2256 speed = 15.0;
2257 else
2258 speed = 18.0;
2259
2260 if (my->count[1] == 0)
2261 dx = -speed + 4.5;
2262 else
2263 dx = speed - 4.5;
2264
2265 tenm_table_add(normal_shot_new(my->x, my->y, dx, speed,
2266 3, -2,
2267 1+((int)(((double)WINDOW_HEIGHT)/speed))));
2268 }
2269
2270 if (my->count[2] >= 15)
2271 my->count[2] = 0;
2272
2273 return 0;
2274 }
2275
2276 static tenm_object *
last_boss_cross_circle_new(int n)2277 last_boss_cross_circle_new(int n)
2278 {
2279 tenm_object *new = NULL;
2280 int *count = NULL;
2281
2282 /* sanity check */
2283 if ((n < 0) || (n > 1))
2284 {
2285 fprintf(stderr, "last_boss_cross_circle_new: strange n (%d)\n", n);
2286 return NULL;
2287 }
2288
2289 count = (int *) malloc(sizeof(int) * 4);
2290 if (count == NULL)
2291 {
2292 fprintf(stderr, "last_boss_cross_circle_new: malloc(count) failed\n");
2293 return NULL;
2294 }
2295
2296 /* list of count
2297 * [0] color (for delete_enemy_shot)
2298 * [1] radius
2299 * [2] shoot timer
2300 * [3] n
2301 */
2302 count[0] = 6;
2303 if (n == 0)
2304 count[1] = 500;
2305 else
2306 count[1] = 2;
2307 count[2] = 0;
2308 count[3] = n;
2309
2310 /* ATTR_ENEMY_SHOT is only to clear it when the player is killed */
2311 new = tenm_object_new("L cross circle", ATTR_ENEMY_SHOT, 0,
2312 0,
2313 (double) (WINDOW_WIDTH / 2),
2314 (double) (WINDOW_HEIGHT / 4),
2315 4, count, 0, NULL, 0, NULL,
2316 (int (*)(tenm_object *, double)) NULL,
2317 (int (*)(tenm_object *, tenm_object *))
2318 NULL,
2319 (int (*)(tenm_object *, const tenm_object *))
2320 (&last_boss_cross_circle_act),
2321 (int (*)(tenm_object *, int))
2322 (&last_boss_cross_circle_draw));
2323 if (new == NULL)
2324 {
2325 fprintf(stderr, "last_boss_cross_circle_new: tenm_object_new failed\n");
2326 if (count != NULL)
2327 free(count);
2328 return NULL;
2329 }
2330
2331 return new;
2332 }
2333
2334 static int
last_boss_cross_circle_act(tenm_object * my,const tenm_object * player)2335 last_boss_cross_circle_act(tenm_object *my, const tenm_object *player)
2336 {
2337 double distance_2;
2338
2339 /* sanity check */
2340 if (my == NULL)
2341 return 0;
2342 if (player == NULL)
2343 return 0;
2344
2345 if (my->count[3] == 0)
2346 {
2347 my->count[1] -= 2;
2348 if (my->count[1] <= 0)
2349 return 1;
2350 }
2351 else
2352 {
2353 my->count[1] += 2;
2354 if (my->count[1] > 500)
2355 return 1;
2356 }
2357
2358 distance_2 = (player->x - my->x) * (player->x - my->x);
2359 distance_2 += (player->y - my->y) * (player->y - my->y);
2360
2361 if (my->count[2] > 0)
2362 {
2363 (my->count[2])--;
2364 }
2365 else
2366 {
2367 if ((distance_2 > (double) ((my->count[1] - 6) * (my->count[1] - 6)))
2368 && (distance_2 < (double) ((my->count[1] + 6) * (my->count[1] + 6))))
2369 {
2370 tenm_table_add(last_boss_cross_new(player->x, player->y, 0));
2371 my->count[2] = 5;
2372 }
2373 }
2374
2375 return 0;
2376 }
2377
2378 static int
last_boss_cross_circle_draw(tenm_object * my,int priority)2379 last_boss_cross_circle_draw(tenm_object *my, int priority)
2380 {
2381 tenm_color color;
2382 int status = 0;
2383
2384 /* sanity check */
2385 if (my == NULL)
2386 return 0;
2387
2388 if (priority != 0)
2389 return 0;
2390
2391 color = tenm_map_color(158, 158, 158);
2392
2393 if (my->count[1] <= 0)
2394 return 1;
2395
2396 if (tenm_draw_circle((int) (my->x), (int) (my->y),
2397 my->count[1], 1, color) != 0)
2398 status = 1;
2399
2400 return status;
2401 }
2402
2403 static tenm_object *
last_boss_cross_new(double x,double y,int n)2404 last_boss_cross_new(double x, double y, int n)
2405 {
2406 tenm_object *new = NULL;
2407 int *count = NULL;
2408
2409 /* sanity check */
2410 if ((n < 0) || (n > 1))
2411 {
2412 fprintf(stderr, "last_boss_cross_new: strange n (%d)\n", n);
2413 return NULL;
2414 }
2415
2416 count = (int *) malloc(sizeof(int) * 2);
2417 if (count == NULL)
2418 {
2419 fprintf(stderr, "last_boss_cross_new: malloc(count) failed\n");
2420 return NULL;
2421 }
2422
2423 /* list of count
2424 * [0] color (for delete_enemy_shot)
2425 * [1] shoot timer
2426 */
2427 count[0] = 3;
2428 count[1] = 12;
2429
2430 /* ATTR_ENEMY_SHOT is only to clear it when the player is killed */
2431 new = tenm_object_new("L cross", ATTR_ENEMY_SHOT, 0,
2432 0, x, y,
2433 2, count, 0, NULL, 0, NULL,
2434 (int (*)(tenm_object *, double)) NULL,
2435 (int (*)(tenm_object *, tenm_object *))
2436 NULL,
2437 (int (*)(tenm_object *, const tenm_object *))
2438 (&last_boss_cross_act),
2439 (int (*)(tenm_object *, int)) (&last_boss_cross_draw));
2440 if (new == NULL)
2441 {
2442 fprintf(stderr, "last_boss_cross_new: tenm_object_new failed\n");
2443 if (count != NULL)
2444 free(count);
2445 return NULL;
2446 }
2447
2448 return new;
2449 }
2450
2451 static int
last_boss_cross_act(tenm_object * my,const tenm_object * player)2452 last_boss_cross_act(tenm_object *my, const tenm_object *player)
2453 {
2454 /* sanity check */
2455 if (my == NULL)
2456 return 0;
2457 if (player == NULL)
2458 return 0;
2459
2460 my->count[1] += 12;
2461 if (my->count[1] > 120)
2462 {
2463 tenm_table_add(laser_point_new(my->x - ((double) my->count[1]), my->y,
2464 9.0,
2465 my->x, my->y,
2466 25.0, 2));
2467 tenm_table_add(laser_point_new(my->x + ((double) my->count[1]), my->y,
2468 9.0,
2469 my->x, my->y,
2470 25.0, 2));
2471 tenm_table_add(laser_point_new(my->x, my->y - ((double) my->count[1]),
2472 9.0,
2473 my->x, my->y,
2474 25.0, 2));
2475 tenm_table_add(laser_point_new(my->x, my->y + ((double) my->count[1]),
2476 9.0,
2477 my->x, my->y,
2478 25.0, 2));
2479 return 1;
2480 }
2481
2482 return 0;
2483 }
2484
2485 static int
last_boss_cross_draw(tenm_object * my,int priority)2486 last_boss_cross_draw(tenm_object *my, int priority)
2487 {
2488 tenm_color color;
2489 int status = 0;
2490
2491 /* sanity check */
2492 if (my == NULL)
2493 return 0;
2494
2495 if (priority != 0)
2496 return 0;
2497
2498 color = tenm_map_color(99, 143, 158);
2499
2500 if (my->count[1] <= 0)
2501 return 1;
2502
2503 if (tenm_draw_line(((int) (my->x)) - my->count[1], (int) (my->y),
2504 ((int) (my->x)) + my->count[1], (int) (my->y),
2505 1, color) != 0)
2506 status = 1;
2507 if (tenm_draw_line((int) (my->x), ((int) (my->y)) - my->count[1],
2508 (int) (my->x), ((int) (my->y)) + my->count[1],
2509 1, color) != 0)
2510 status = 1;
2511
2512 return status;
2513 }
2514