1 /* $Id: mankanshoku.c,v 1.95 2005/01/06 06:16:42 oohara Exp $ */
2
3 #include <stdio.h>
4 /* malloc, rand */
5 #include <stdlib.h>
6 /* strlen, strcmp */
7 #include <string.h>
8
9 #include "const.h"
10 #include "tenm_object.h"
11 #include "tenm_graphic.h"
12 #include "tenm_primitive.h"
13 #include "util.h"
14 #include "player-shot.h"
15 #include "tenm_table.h"
16 #include "background.h"
17 #include "chain.h"
18 #include "laser.h"
19 #include "normal-shot.h"
20 #include "tenm_math.h"
21 #include "fragment.h"
22 #include "explosion.h"
23 #include "normal-enemy.h"
24 #include "score.h"
25 #include "wall-8.h"
26 #include "silver-chimera.h"
27 #include "warning.h"
28
29 #include "mankanshoku.h"
30
31 static int mankanshoku_move(tenm_object *my, double turn_per_frame);
32 static int mankanshoku_hit(tenm_object *my, tenm_object *your);
33 static void mankanshoku_next(tenm_object *my);
34 static int mankanshoku_act(tenm_object *my, const tenm_object *player);
35 static int mankanshoku_draw(tenm_object *my, int priority);
36 static int mankanshoku_green(const tenm_object *my);
37
38 tenm_object *
mankanshoku_new(void)39 mankanshoku_new(void)
40 {
41 tenm_primitive **p = NULL;
42 tenm_object *new = NULL;
43 int *count = NULL;
44 double *count_d = NULL;
45 double x = (double) (WINDOW_WIDTH / 2);
46 double y = -255.0;
47
48 p = (tenm_primitive **) malloc(sizeof(tenm_primitive *) * 1);
49 if (p == NULL)
50 {
51 fprintf(stderr, "mankanshoku_new: malloc(p) failed\n");
52 return NULL;
53 }
54
55 p[0] = (tenm_primitive *) tenm_polygon_new(8,
56 x + 60.0, y - 15.0,
57 x + 60.0, y + 15.0,
58 x + 50.0, y + 25.0,
59 x - 50.0, y + 25.0,
60 x - 60.0, y + 15.0,
61 x - 60.0, y - 15.0,
62 x - 50.0, y - 25.0,
63 x + 50.0, y - 25.0);
64 if (p[0] == NULL)
65 {
66 fprintf(stderr, "mankanshoku_new: cannot set p[0]\n");
67 free(p);
68 return NULL;
69 }
70
71 count = (int *) malloc(sizeof(int) * 7);
72 if (count == NULL)
73 {
74 fprintf(stderr, "mankanshoku_new: malloc(count) failed\n");
75 (p[0])->delete(p[0]);
76 free(p);
77 return NULL;
78 }
79 count_d = (double *) malloc(sizeof(double) * 3);
80 if (count_d == NULL)
81 {
82 fprintf(stderr, "mankanshoku_new: malloc(count_d) failed\n");
83 free(count);
84 (p[0])->delete(p[0]);
85 free(p);
86 return NULL;
87 }
88
89 /* list of count
90 * [0] for deal_damage
91 * [1] "damaged" timer
92 * [2] life mode
93 * [3] life timer
94 * [4] the time when we escaped / were killed
95 * [5] add enemy mode
96 * [6] add enemy timer
97 */
98 /* list of count_d
99 * [0] speed x
100 * [1] speed y
101 */
102
103 count[0] = 0;
104 count[1] = 0;
105 count[2] = 0;
106 count[3] = 0;
107 count[4] = 0;
108 count[5] = (rand() % 2) * 3;
109 count[6] = 0;
110
111 count_d[0] = 0.0;
112 count_d[1] = 7.5;
113
114 new = tenm_object_new("Mankanshoku", ATTR_ENEMY | ATTR_OBSTACLE,
115 ATTR_PLAYER_SHOT,
116 750, x, y,
117 7, count, 3, count_d, 1, p,
118 (int (*)(tenm_object *, double))
119 (&mankanshoku_move),
120 (int (*)(tenm_object *, tenm_object *))
121 (&mankanshoku_hit),
122 (int (*)(tenm_object *, const tenm_object *))
123 (&mankanshoku_act),
124 (int (*)(tenm_object *, int))
125 (&mankanshoku_draw));
126
127 if (new == NULL)
128 {
129 fprintf(stderr, "mankanshoku_new: tenm_object_new failed\n");
130 if (count_d != NULL)
131 free(count_d);
132 if (count != NULL)
133 free(count);
134 (p[0])->delete(p[0]);
135 free(p);
136 return NULL;
137 }
138
139 return new;
140 }
141
142 static int
mankanshoku_move(tenm_object * my,double turn_per_frame)143 mankanshoku_move(tenm_object *my, double turn_per_frame)
144 {
145 double dx_temp;
146 double dy_temp;
147
148 /* sanity check */
149 if (my == NULL)
150 {
151 fprintf(stderr, "mankanshoku_move: my is NULL\n");
152 return 0;
153 }
154 if (turn_per_frame <= 0.5)
155 {
156 fprintf(stderr, "mankanshoku_move: strange turn_per_frame (%f)\n",
157 turn_per_frame);
158 return 0;
159 }
160
161 if (my->count[2] != 0)
162 return 0;
163
164 dx_temp = my->count_d[0] / turn_per_frame;
165 dy_temp = my->count_d[1] / turn_per_frame;
166 my->x += dx_temp;
167 my->y += dy_temp;
168 if (my->mass != NULL)
169 tenm_move_mass(my->mass, dx_temp, dy_temp);
170
171 if ((my->count[3] >= 2344) && (my->y > ((double) WINDOW_HEIGHT) + 120.0))
172 mankanshoku_next(my);
173
174 return 0;
175 }
176
177 static int
mankanshoku_hit(tenm_object * my,tenm_object * your)178 mankanshoku_hit(tenm_object *my, tenm_object *your)
179 {
180 int n;
181
182 /* sanity check */
183 if (my == NULL)
184 {
185 fprintf(stderr, "mankanshoku_hit: my is NULL\n");
186 return 0;
187 }
188 if (your == NULL)
189 {
190 fprintf(stderr, "mankanshoku_hit: your is NULL\n");
191 return 0;
192 }
193
194 if (my->count[2] != 0)
195 return 0;
196 if (!(your->attr & ATTR_PLAYER_SHOT))
197 return 0;
198
199 deal_damage(my, your, 0);
200 if (mankanshoku_green(my))
201 add_chain(my, your);
202 my->count[1] = 41;
203
204 if (my->hit_point <= 0)
205 {
206 add_score(100);
207
208 if (mankanshoku_green(my))
209 n = 8;
210 else
211 n = 7;
212 tenm_table_add(explosion_new(my->x, my->y,
213 my->count_d[0] * 0.5,
214 my->count_d[1] * 0.5,
215 1, 1000, n, 8.0, 6));
216 tenm_table_add(fragment_new(my->x, my->y,
217 my->count_d[0] * 0.5, my->count_d[1] * 0.5,
218 30.0, 30, n, 5.0, 0.0, 20));
219
220 mankanshoku_next(my);
221 return 0;
222 }
223
224 return 0;
225 }
226
227 static void
mankanshoku_next(tenm_object * my)228 mankanshoku_next(tenm_object *my)
229 {
230 /* sanity check */
231 if (my == NULL)
232 return;
233
234 /* no explosion here --- this is called when we escape
235 * as well as we are killed
236 */
237 my->count[2] = 1;
238 my->count[4] = my->count[3];
239 if (my->count[4] < 1082)
240 my->count[4] = 1082;
241 my->count[1] = 0;
242
243 /* don't modify my->attr or my->hit_mask here, or the player shot
244 * may fly through the enemy */
245 tenm_mass_delete(my->mass);
246 my->mass = NULL;
247 }
248
249 static int
mankanshoku_act(tenm_object * my,const tenm_object * player)250 mankanshoku_act(tenm_object *my, const tenm_object *player)
251 {
252 int i;
253 int t;
254 int theta1;
255 int theta2;
256 int temp;
257 double speed;
258 double dx;
259 double dy;
260 double result[2];
261 double v[2];
262 double x;
263
264 /* sanity check */
265 if (my == NULL)
266 {
267 fprintf(stderr, "mankanshoku_act: my is NULL\n");
268 return 0;
269 }
270 if (player == NULL)
271 return 0;
272
273 /* for deal_damage */
274 my->count[0] = 0;
275
276 /* "damaged" count down */
277 if (my->count[1] > 0)
278 (my->count[1])--;
279
280 (my->count[3])++;
281
282 /* dead / escaped */
283 if (my->count[2] == 1)
284 {
285 if (my->count[3] == my->count[4] + 160)
286 tenm_table_add(warning_new());
287
288 if (my->count[3] == my->count[4] + 290)
289 {
290 tenm_table_add(silver_chimera_new());
291 return 1;
292 }
293 }
294
295 /* move */
296 if (my->count[3] < 75)
297 my->count_d[1] = 7.5 - ((double) (my->count[3])) * 0.1;
298 else if (my->count[3] < 1032)
299 my->count_d[1] = 0.0;
300 else if (my->count[3] < 1082)
301 my->count_d[1] = ((double) (my->count[3] - 1032)) * 0.1;
302 else if (my->count[3] < 1187)
303 my->count_d[1] = 5.0 - ((double) (my->count[3] - 1082)) * 0.1;
304 else if (my->count[3] < 2344)
305 my->count_d[1] = 0.0;
306 else
307 my->count_d[1] = 7.5;
308
309 /* add wall */
310 if ((my->count[3] >= 1133) && (my->count[3] < 9999)
311 && ((my->count[2] == 0) || (my->count[3] < my->count[4] + 72))
312 && ((my->count[3] - 1133) % 24 == 0))
313 {
314 tenm_table_add(wall_8_new(30.0, -29.0, 0, my->count[3] + 2458));
315 tenm_table_add(wall_8_new(((double) WINDOW_WIDTH) - 30.0, -29.0, 0,
316 my->count[3] + 2458));
317 }
318
319 t = my->count[3] - 1187;
320 if (t < 0)
321 return 0;
322
323 /* chase the player */
324 if (player->x < 220.0)
325 x = 120.0;
326 else if (player->x < 420.0)
327 x = 320.0;
328 else
329 x = 520.0;
330
331 if ((my->x + 10.0 > x) && (my->x - 10.0 < x))
332 my->count_d[0] = x - my->x;
333 else if (my->x < x)
334 my->count_d[0] = 10.0;
335 else
336 my->count_d[0] = -10.0;
337 if (my->x + my->count_d[0] < 120.0)
338 my->count_d[0] = 120.0 - my->x;
339 if (my->x + my->count_d[0] > 520.0)
340 my->count_d[0] = 520.0 - my->x;
341 if (t >= 1058)
342 my->count_d[0] = 0.0;
343
344 /* add normal enemy */
345 if (my->count[5] >= 0)
346 {
347 (my->count[6])++;
348 if ((my->count[2] != 0) && (my->count[6] < 48))
349 {
350 my->count[5] = -1;
351 }
352 else if ((my->count[6] >= 48) && (my->count[6] <= 60)
353 && (my->count[6] % 6 == 0))
354 {
355 switch (my->count[5])
356 {
357 case 0:
358 x = 120.0 + ((double) (my->count[6] - 56)) * 3.0;
359 break;
360 case 1:
361 x = 320.0 - ((double) (my->count[6] - 48)) * 3.0;
362 break;
363 case 2:
364 x = 320.0 + ((double) (my->count[6] - 48)) * 3.0;
365 break;
366 case 3:
367 x = 520.0 - ((double) (my->count[6] - 56)) * 3.0;
368 break;
369 default:
370 fprintf(stderr, "mankanshoku_act: undefined my->count[5] (add enemy) "
371 "(%d)\n", my->count[5]);
372 x = ((double) (WINDOW_WIDTH / 2));
373 break;
374 }
375 if (my->count[6] == 48)
376 temp = 37;
377 else
378 temp = 9999;
379 tenm_table_add(normal_enemy_new(x, -19.0,
380 BALL_SOLDIER, ENEMY_TYPE_WEAK,
381 0, -1, 0, -1, 0, 1, 2,
382 /* move 0 */
383 9999,
384 0.0, 7.5, 0.0, 0.0,
385 0.0, 0.0, 0.0, 0.0, 0,
386 /* shoot 0 */
387 21, temp, 34, 0, 0, 1,
388 /* shoot 1 */
389 9999, temp, 55 % temp, 0, 1, 1));
390 }
391 if (my->count[6] >= 60)
392 {
393 switch (my->count[5])
394 {
395 case 0:
396 case 3:
397 my->count[5] = 1 + rand() % 2;
398 break;
399 case 1:
400 my->count[5] = 0;
401 break;
402 case 2:
403 my->count[5] = 3;
404 break;
405 default:
406 fprintf(stderr, "mankanshoku_act: undefined my->count[5] "
407 "(mode change) (%d)\n", my->count[5]);
408 my->count[5] = 1;
409 break;
410 }
411 if ((t >= 840) || (my->count[2] != 0))
412 my->count[5] = -1;
413
414 my->count[6] = 0;
415 }
416 }
417
418 /* shoot */
419 if (my->count[2] != 0)
420 return 0;
421
422 if (t < 907)
423 {
424 if (t % 121 == 0)
425 {
426 tenm_table_add(laser_angle_new(my->x - 50.0, my->y, 6.5,
427 125, 25.0, 2));
428 tenm_table_add(laser_angle_new(my->x - 50.0, my->y, 6.5,
429 146, 25.0, 2));
430 tenm_table_add(laser_angle_new(my->x - 50.0, my->y, 6.5,
431 167, 25.0, 2));
432
433 tenm_table_add(laser_angle_new(my->x + 50.0, my->y, 6.5,
434 55, 25.0, 2));
435 tenm_table_add(laser_angle_new(my->x + 50.0, my->y, 6.5,
436 34, 25.0, 2));
437 tenm_table_add(laser_angle_new(my->x + 50.0, my->y, 6.5,
438 13, 25.0, 2));
439 }
440 if (t % 121 == 11)
441 {
442 tenm_table_add(laser_angle_new(my->x - 50.0, my->y, 6.5,
443 95, 25.0, 2));
444 tenm_table_add(laser_angle_new(my->x - 50.0, my->y, 7.5,
445 116, 25.0, 2));
446 tenm_table_add(laser_angle_new(my->x - 50.0, my->y, 8.5,
447 137, 25.0, 2));
448
449 tenm_table_add(laser_angle_new(my->x + 50.0, my->y, 6.5,
450 85, 25.0, 2));
451 tenm_table_add(laser_angle_new(my->x + 50.0, my->y, 7.5,
452 64, 25.0, 2));
453 tenm_table_add(laser_angle_new(my->x + 50.0, my->y, 8.5,
454 43, 25.0, 2));
455 }
456 if (t % 121 == 22)
457 {
458 tenm_table_add(laser_angle_new(my->x - 50.0, my->y, 6.5,
459 65, 25.0, 2));
460 tenm_table_add(laser_angle_new(my->x - 50.0, my->y, 8.5,
461 86, 25.0, 2));
462 tenm_table_add(laser_angle_new(my->x - 50.0, my->y, 10.5,
463 107, 25.0, 2));
464
465 tenm_table_add(laser_angle_new(my->x + 50.0, my->y, 6.5,
466 115, 25.0, 2));
467 tenm_table_add(laser_angle_new(my->x + 50.0, my->y, 8.5,
468 94, 25.0, 2));
469 tenm_table_add(laser_angle_new(my->x + 50.0, my->y, 10.5,
470 73, 25.0, 2));
471 }
472
473 if ((t % 121 == 55) || (t % 121 == 88))
474 {
475 speed = 6.0;
476 if (t % 121 == 55)
477 theta1 = 45;
478 else
479 theta1 = 77;
480 theta2 = 113;
481
482 dx = speed * tenm_cos(theta1);
483 dy = speed * tenm_sin(theta1);
484 v[0] = speed * tenm_cos(180 - theta2) * tenm_cos(theta1 - theta2);
485 v[1] = speed * tenm_cos(180 - theta2) * tenm_sin(theta1 - theta2);
486
487 for (i = 0; i < 6; i++)
488 {
489 result[0] = v[0];
490 result[1] = v[1];
491 vector_rotate(result, v, i * 30);
492 tenm_table_add(normal_shot_new(my->x - 50.0, my->y,
493 dx + result[0], dy + result[1],
494 1, -2, 0));
495 tenm_table_add(normal_shot_new(my->x + 50.0, my->y,
496 -(dx + result[0]), dy + result[1],
497 1, -2, 0));
498 }
499 }
500 }
501 else if ((t >= 989) && (t < 1127))
502 {
503 speed = 7.0;
504 if (t % 46 == 0)
505 {
506 tenm_table_add(laser_point_new(my->x + 120.0 * tenm_cos(-15),
507 my->y + 120.0 * tenm_sin(-15),
508 speed,
509 player->x, player->y - 150.0,
510 25.0, 0));
511 tenm_table_add(laser_point_new(my->x + 120.0 * tenm_cos(-165),
512 my->y + 120.0 * tenm_sin(-165),
513 speed,
514 player->x, player->y - 150.0,
515 25.0, 0));
516 tenm_table_add(laser_point_new(my->x + 120.0 * tenm_cos(-45),
517 my->y + 120.0 * tenm_sin(-45),
518 speed,
519 player->x, player->y - 75.0,
520 25.0, 0));
521 tenm_table_add(laser_point_new(my->x + 120.0 * tenm_cos(-135),
522 my->y + 120.0 * tenm_sin(-135),
523 speed,
524 player->x, player->y - 75.0,
525 25.0, 0));
526 tenm_table_add(laser_point_new(my->x + 120.0 * tenm_cos(-75),
527 my->y + 120.0 * tenm_sin(-75),
528 speed,
529 player->x, player->y,
530 25.0, 0));
531 tenm_table_add(laser_point_new(my->x + 120.0 * tenm_cos(-105),
532 my->y + 120.0 * tenm_sin(-105),
533 speed,
534 player->x, player->y,
535 25.0, 0));
536 }
537 if (t % 46 == 23)
538 {
539 tenm_table_add(laser_point_new(my->x + 120.0 * tenm_cos(-15),
540 my->y + 120.0 * tenm_sin(-15),
541 speed,
542 player->x, player->y,
543 25.0, 0));
544 tenm_table_add(laser_point_new(my->x + 120.0 * tenm_cos(-165),
545 my->y + 120.0 * tenm_sin(-165),
546 speed,
547 player->x, player->y,
548 25.0, 0));
549 tenm_table_add(laser_point_new(my->x + 120.0 * tenm_cos(-45),
550 my->y + 120.0 * tenm_sin(-45),
551 speed,
552 player->x, player->y - 75.0,
553 25.0, 0));
554 tenm_table_add(laser_point_new(my->x + 120.0 * tenm_cos(-135),
555 my->y + 120.0 * tenm_sin(-135),
556 speed,
557 player->x, player->y - 75.0,
558 25.0, 0));
559 tenm_table_add(laser_point_new(my->x + 120.0 * tenm_cos(-75),
560 my->y + 120.0 * tenm_sin(-75),
561 speed,
562 player->x, player->y - 150.0,
563 25.0, 0));
564 tenm_table_add(laser_point_new(my->x + 120.0 * tenm_cos(-105),
565 my->y + 120.0 * tenm_sin(-105),
566 speed,
567 player->x, player->y - 150.0,
568 25.0, 0));
569 }
570 }
571
572 return 0;
573 }
574
575 static int
mankanshoku_draw(tenm_object * my,int priority)576 mankanshoku_draw(tenm_object *my, int priority)
577 {
578 int status = 0;
579 tenm_color color;
580 char temp[32];
581 int i;
582
583 /* sanity check */
584 if (my == NULL)
585 {
586 fprintf(stderr, "mankanshoku_draw: my is NULL\n");
587 return 0;
588 }
589
590 if (priority != 0)
591 return 0;
592 if (my->count[2] != 0)
593 return 0;
594
595 /* decoration */
596 if (mankanshoku_green(my))
597 {
598 if (my->count[1] >= 40)
599 color = tenm_map_color(181, 190, 92);
600 else
601 color = tenm_map_color(157, 182, 123);
602 }
603 else
604 {
605 if (my->count[1] >= 40)
606 color = tenm_map_color(200, 164, 92);
607 else
608 color = tenm_map_color(182, 147, 123);
609 }
610
611 for (i = -15; i >= -165; i -= 30)
612 if (tenm_draw_line(((int) (my->x + 80.0 * tenm_cos(i))),
613 ((int) (my->y + 80.0 * tenm_sin(i))),
614 ((int) (my->x + 120.0 * tenm_cos(i))),
615 ((int) (my->y + 120.0 * tenm_sin(i))),
616 1, color) != 0)
617 status = 1;
618
619 /* body */
620 if (mankanshoku_green(my))
621 {
622 if (my->count[1] >= 40)
623 color = tenm_map_color(109, 125, 9);
624 else
625 color = tenm_map_color(61, 95, 13);
626 }
627 else
628 {
629 if (my->count[1] >= 40)
630 color = tenm_map_color(135, 89, 9);
631 else
632 color = tenm_map_color(95, 47, 13);
633 }
634
635 if (tenm_draw_line(((int) (my->x + 60.0)),
636 ((int) (my->y - 15.0)),
637 ((int) (my->x + 60.0)),
638 ((int) (my->y + 15.0)),
639 3, color) != 0)
640 status = 1;
641 if (tenm_draw_line(((int) (my->x + 60.0)),
642 ((int) (my->y + 15.0)),
643 ((int) (my->x + 50.0)),
644 ((int) (my->y + 25.0)),
645 3, color) != 0)
646 status = 1;
647 if (tenm_draw_line(((int) (my->x + 50.0)),
648 ((int) (my->y + 25.0)),
649 ((int) (my->x - 50.0)),
650 ((int) (my->y + 25.0)),
651 3, color) != 0)
652 status = 1;
653 if (tenm_draw_line(((int) (my->x - 50.0)),
654 ((int) (my->y + 25.0)),
655 ((int) (my->x - 60.0)),
656 ((int) (my->y + 15.0)),
657 3, color) != 0)
658 status = 1;
659 if (tenm_draw_line(((int) (my->x - 60.0)),
660 ((int) (my->y + 15.0)),
661 ((int) (my->x - 60.0)),
662 ((int) (my->y - 15.0)),
663 3, color) != 0)
664 status = 1;
665 if (tenm_draw_line(((int) (my->x - 60.0)),
666 ((int) (my->y - 15.0)),
667 ((int) (my->x - 50.0)),
668 ((int) (my->y - 25.0)),
669 3, color) != 0)
670 status = 1;
671 if (tenm_draw_line(((int) (my->x - 50.0)),
672 ((int) (my->y - 25.0)),
673 ((int) (my->x + 50.0)),
674 ((int) (my->y - 25.0)),
675 3, color) != 0)
676 status = 1;
677 if (tenm_draw_line(((int) (my->x + 50.0)),
678 ((int) (my->y - 25.0)),
679 ((int) (my->x + 60.0)),
680 ((int) (my->y - 15.0)),
681 3, color) != 0)
682 status = 1;
683
684 /* hit point stat */
685 if ((priority == 0) && (my->count[1] > 0))
686 {
687 sprintf(temp, "%d", my->hit_point);
688 if (draw_string(((int) my->x) - 10, (int) my->y,
689 temp, (int) strlen(temp)) != 0)
690 {
691 fprintf(stderr, "mankanshoku_draw: draw_string failed\n");
692 status = 1;
693 }
694 }
695
696 return status;
697 }
698
699 /* return 1 (true) or 0 (false) */
700 static int
mankanshoku_green(const tenm_object * my)701 mankanshoku_green(const tenm_object *my)
702 {
703 /* sanity check */
704 if (my == NULL)
705 return 0;
706
707 if ((my->count[3] >= 1192) && (my->count[3] < 2314))
708 return 1;
709
710 return 0;
711 }
712