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