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