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