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