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