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