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