1 /* xsoldier, a shoot 'em up game with "not shooting" bonus
2  * Copyright (C) 1997 Yuusuke HASHIMOTO <s945750@educ.info.kanagawa-u.ac.jp>
3  * Copyright (C) 2002 Oohara Yuuma  <oohara@libra.interq.or.jp>
4  *
5  * This is a copyleft program.  See the file LICENSE for details.
6  */
7 /* $Id: boss.c,v 1.21 2002/05/26 08:31:59 oohara Exp $ */
8 
9 /* DEBUG is defined in config.h */
10 #include <config.h>
11 /* rand */
12 #include <stdlib.h>
13 
14 /*
15 #include <X11/Xlib.h>
16 #include <X11/xpm.h>
17 */
18 
19 #include "image.h"
20 #include "xsoldier.h"
21 #include "manage.h"
22 #include "common.h"
23 #include "enemyshot.h"
24 #include "callback.h"
25 #include "boss.h"
26 #include "enemy.h"
27 #include "extern.h"
28 #include "sin.h"
29 
30 /* local functions for the last boss */
31 static DelAtt BossAct8_dead(ObjData *my);
32 static DelAtt BossAct8_rand_shot(ObjData *my);
33 static DelAtt BossAct8_ring_shot(ObjData *my);
34 static DelAtt BossAct8_bound_shot(ObjData *my);
35 static DelAtt BossAct8_homing_shot(ObjData *my);
36 static DelAtt BossAct8_charge_shot(ObjData *my);
37 static DelAtt BossAct8_n_way_shot(ObjData *my);
38 static void BossAct8_next(ObjData *my, int span);
39 
40 /* definition of objects
41  * - initialization function
42  * - action function
43  * - hit function
44  *
45  * initialization add action function and display/hit function to the table
46  */
47 
NewBoss1(void)48 int NewBoss1(void)
49 {
50     manage->New.Data.hitAtt = MEnemy;
51     manage->New.Data.hitMask = MPlayer | MPShot;
52 
53     manage->New.Data.X = FieldW/2;
54     manage->New.Data.Y = -90;
55 
56     manage->New.Data.HP = 120;
57     manage->New.Data.Point = 5000;
58     manage->New.Data.EnemyAtt = BossDel;
59 
60     manage->New.Data.Width = 150;
61     manage->New.Data.Height = 180;
62 
63     manage->New.Data.Cnt[0] = 0;
64     manage->New.Data.Cnt[1] = 200; /* immutable time */
65     manage->New.Data.Cnt[2] = 0; /* image counter*/
66     manage->New.Data.Cnt[3] = 10; /* x move */
67     manage->New.Data.Cnt[4] = 0; /* y move */
68     manage->New.Data.Cnt[5] = 0;  /* laser counter */
69     manage->New.Data.Cnt[6] = 0;  /* normal shot counter */
70 
71     manage->New.Grp.image = Boss1Image;
72     return NewObj(MEnemy,BossAct1,BossHit1,DrawImage);
73 }
74 
BossAct1(ObjData * my)75 DelAtt BossAct1(ObjData *my)
76 {
77   int i;
78 
79     if (my->Cnt[0] < my->Cnt[1])
80     {/* appears slowly */
81 	my->Y++;
82 	my->Cnt[0]++;
83 	return NoneDel;
84     }
85 
86     if (manage->BossTime <= 0)
87     {
88       if (my->Y > 0 - my->Height/2 - 100)
89         (my->Y) -= 4;
90       if (my->Y < 0 - my->Height/2 - 50)
91       {
92         if ((player->Ships <= 0) && (manage->player[0]->Data.Cnt[3] != 0))
93           return NoneDel;
94         else
95           return BossDel;
96       }
97       else
98 	return NoneDel;
99     }
100 
101     (manage->BossTime)--;
102 
103     if (my->Cnt[6] >= (100- (manage->Loop)*10) )
104     {
105         ShotToAngle(my->X, my->Y, 50, 10);
106         ShotToAngle(my->X, my->Y, 70, 10);
107         ShotToAngle(my->X, my->Y, 90, 10);
108         ShotToAngle(my->X, my->Y, 110, 10);
109         ShotToAngle(my->X, my->Y, 130, 10);
110         my->Cnt[6] =0;
111     }
112     else
113 	(my->Cnt[6])++;
114 
115     if (my->Cnt[5] >= (25-manage->Loop*3))
116     {
117       for (i = 1; i< manage->Loop; i++)
118 	    ShotToAngle(my->X,my->Y,rand()%180,10);
119       if (manage->Loop >1)
120 	    ShotToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,10);
121 	LaserShot(my->X-30,my->Y,20);
122 	LaserShot(my->X+30,my->Y,20);
123 	LaserShot(my->X-80,my->Y,20);
124 	LaserShot(my->X+80,my->Y,20);
125 
126 	my->Cnt[5] = 0;
127     }
128     else
129 	my->Cnt[5]++;
130 
131     if ((my->X+my->Cnt[3]>FieldW) || (my->X+my->Cnt[3]<0))
132 	my->Cnt[3] = my->Cnt[3]*(-1);
133 
134     my->X += my->Cnt[3];
135 
136     return NoneDel;
137 }
138 
BossHit1(ObjData * my,ObjData * your)139 DelAtt BossHit1(ObjData *my, ObjData *your)
140 {
141   int temp = your->Attack;
142 
143   if ((my->Cnt[0] < my->Cnt[1]) || (manage->BossTime <=0))
144     {
145       return NoneDel;
146     }
147 
148     if (my->HP < temp)
149     {
150       temp = my->HP;
151     }
152 
153     my->HP -= temp;
154     player->Rec[0].score += temp;
155 
156     if (my->HP <= 0)
157     {
158       player->Rec[0].score -= 1;
159         NewBomb(my->X,my->Y);
160         NewBomb(my->X+rand()%100-50,my->Y+rand()%100-50);
161         NewBomb(my->X+rand()%100-50,my->Y+rand()%100-50);
162         NewBomb(my->X+rand()%100-50,my->Y+rand()%100-50);
163         NewBomb(my->X+rand()%100-50,my->Y+rand()%100-50);
164         NewBomb(my->X+rand()%100-50,my->Y+rand()%100-50);
165         NewBomb(my->X+rand()%100-50,my->Y+rand()%100-50);
166 
167         my->showDamegeTime = 0;
168         return my->EnemyAtt;
169     }
170     else
171     {
172       my->showDamegeTime = 15;
173       return NoneDel;
174     }
175 
176 }
177 
NewBoss2(void)178 int NewBoss2(void)
179 {
180     manage->New.Data.hitAtt = MEnemy;
181     manage->New.Data.hitMask = MPlayer | MPShot;
182 
183     manage->New.Data.X = FieldW/2;
184     manage->New.Data.Y = -60;
185 
186     manage->New.Data.HP = 200;
187     manage->New.Data.Point = 5000;
188     manage->New.Data.EnemyAtt = BossDel;
189 
190     manage->New.Data.Width = 90;
191     manage->New.Data.Height = 130;
192 
193     manage->New.Data.Cnt[0] = 0;
194     manage->New.Data.Cnt[1] = 200; /* immutable time */
195     manage->New.Data.Cnt[2] = 0; /* image counter */
196 
197     manage->New.Data.Cnt[3] = 0;
198     manage->New.Data.Cnt[4] = 0;
199     manage->New.Data.Cnt[5] = 0; /* normal shot counter */
200 
201     manage->New.Grp.image = Boss2Image;
202     return NewObj(MEnemy,BossAct2,BossHit1,DrawImage);
203 }
204 
BossAct2(ObjData * my)205 DelAtt BossAct2(ObjData *my)
206 {
207     if (my->Cnt[0] < my->Cnt[1])
208     {/* appears slowly */
209 	my->Y++;
210 	my->Cnt[0]++;
211 	return NoneDel;
212     }
213 
214     if (manage->BossTime <= 0)
215     {
216       if (my->Y > 0 - my->Height/2 - 100)
217         (my->Y) -= 4;
218       if (my->Y < 0 - my->Height/2 - 50)
219       {
220         if ((player->Ships <= 0) && (manage->player[0]->Data.Cnt[3] != 0))
221           return NoneDel;
222         else
223           return BossDel;
224       }
225       else
226 	return NoneDel;
227     }
228 
229     (manage->BossTime)--;
230 
231     if (manage->Loop > 2)
232     {
233 	if (my->Cnt[5] >= 90- (manage->Loop)*10)
234 	{
235 	    ShotToPoint(my->X+40,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%3 + 5);
236 	    ShotToPoint(my->X   ,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,8);
237 	    ShotToPoint(my->X-40,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%5 + 3);
238             my->Cnt[5] = 0;
239 	}
240 	else
241             (my->Cnt[5])++;
242     }
243 
244     if (my->Cnt[3] >= (15-manage->Loop*3))
245     {
246       if (manage->Loop > 1)
247       {
248         if (manage->player[0]->Data.Y < my->Y)
249           ShotToAngle(my->X, my->Y, 270, 10);
250         else
251           ShotToAngle(my->X, my->Y, 90, 10);
252       }
253 
254       HomingShot(my->X-20,my->Y-10,-10,-10);
255       HomingShot(my->X+20,my->Y-10, 10,-10);
256       my->Cnt[3] = 0;
257     }
258     else
259 	my->Cnt[3]++;
260 
261     if (my->X > manage->player[0]->Data.X)
262     {
263 	if (my->X - manage->player[0]->Data.X > 20)
264 	{
265 	    my->X -= 10;
266 	}
267 	else
268 	{
269 	    my->Cnt[4]++;
270 	    my->X --;
271 	}
272 
273 	if (my->Cnt[4] > 10)
274 	{
275 	    LaserShot(my->X-40,my->Y,30);
276 	    LaserShot(my->X+40,my->Y,30);
277 	    my->Cnt[4] = 0;
278 	}
279     }
280     else
281     {
282 	if (manage->player[0]->Data.X - my->X > 20)
283 	{
284 	    my->X += 10;
285 	}
286 	else
287 	{
288 	    my->Cnt[4]++;
289 	    my->X ++;
290 	}
291 
292 	if (my->Cnt[4] > 10)
293 	{
294 	    LaserShot(my->X-40,my->Y,30);
295 	    LaserShot(my->X+40,my->Y,30);
296 	    my->Cnt[4] = 0;
297 	}
298     }
299 
300     return NoneDel;
301 }
302 
NewBoss3(void)303 int NewBoss3(void)
304 {
305     manage->New.Data.hitAtt = MEnemy;
306     manage->New.Data.hitMask = MPlayer | MPShot;
307 
308     manage->New.Data.X = FieldW/2;
309     manage->New.Data.Y = -80;
310 
311     manage->New.Data.HP = 330;
312     manage->New.Data.Point = 6000;
313     manage->New.Data.EnemyAtt = BossDel;
314 
315     manage->New.Data.Width = 130;
316     manage->New.Data.Height = 130;
317 
318     manage->New.Data.Cnt[0] = 0;
319     manage->New.Data.Cnt[1] = 200; /* immutable time */
320     manage->New.Data.Cnt[2] = 0; /* image counter */
321     manage->New.Data.Cnt[3] = 10; /* x move */
322     manage->New.Data.Cnt[4] = 0; /* y move */
323     manage->New.Data.Cnt[5] = 0;  /* laser counter */
324     manage->New.Data.Cnt[6] = 0; /* missile counter */
325 
326     manage->New.Grp.image = Boss3Image;
327     return NewObj(MEnemy,BossAct3,BossHit1,DrawImage);
328 }
329 
BossAct3(ObjData * my)330 DelAtt BossAct3(ObjData *my)
331 {
332     if (my->Cnt[0] < my->Cnt[1])
333     {/* appears slowly */
334 	my->Y++;
335 	my->Cnt[0]++;
336 	return NoneDel;
337     }
338 
339     if (manage->BossTime <= 0)
340     {
341       if (my->Y > 0 - my->Height/2 - 100)
342         (my->Y) -= 4;
343       if (my->Y < 0 - my->Height/2 - 50)
344       {
345         if ((player->Ships <= 0) && (manage->player[0]->Data.Cnt[3] != 0))
346           return NoneDel;
347         else
348           return BossDel;
349       }
350       else
351 	return NoneDel;
352     }
353 
354     (manage->BossTime)--;
355 
356     if (my->Cnt[6] >= (80 - manage->Loop*10))
357     {
358 	HomingShot(my->X,my->Y,0,10);
359 	HomingShot(my->X,my->Y,10,0);
360 	HomingShot(my->X,my->Y,0,-10);
361 	HomingShot(my->X,my->Y,-10,0);
362 	HomingShot(my->X,my->Y,10,10);
363 	HomingShot(my->X,my->Y,-10,10);
364 	HomingShot(my->X,my->Y,10,-10);
365 	HomingShot(my->X,my->Y,-10,-10);
366 
367 	my->Cnt[6] = 0;
368     }
369     else
370       my->Cnt[6]++;
371 
372     if (my->Cnt[5] >= (25 - manage->Loop*2))
373     {
374       if (manage->Loop >1)
375 	LaserShot(my->X- 120+ (rand()%5)*60,my->Y,25);
376       if (manage->Loop >2)
377 	    ShotToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,18);
378 	LaserShot(my->X-30,my->Y,25);
379 	LaserShot(my->X+30,my->Y,25);
380 	LaserShot(my->X-90,my->Y,25);
381 	LaserShot(my->X+90,my->Y,25);
382 	LaserShot(my->X-150,my->Y,25);
383 	LaserShot(my->X+150,my->Y,25);
384 
385 	my->Cnt[5] = 0;
386     }
387     else
388 	my->Cnt[5]++;
389 
390     if ((my->X+my->Cnt[3]>FieldW) || (my->X+my->Cnt[3]<0))
391 	my->Cnt[3] = my->Cnt[3]*(-1);
392 
393     my->X += my->Cnt[3];
394 
395     return NoneDel;
396 }
397 
NewBoss4(void)398 int NewBoss4(void)
399 {
400     manage->New.Data.hitAtt = MEnemy;
401     manage->New.Data.hitMask = MPlayer | MPShot;
402 
403     manage->New.Data.X = FieldW/2;
404     manage->New.Data.Y = -90;
405 
406     manage->New.Data.inertX = 0;
407     manage->New.Data.inertY = 0;
408 
409     manage->New.Data.HP = 550;
410     manage->New.Data.Point = 6000;
411     manage->New.Data.EnemyAtt = BossDel;
412 
413     manage->New.Data.Width = 300;
414     manage->New.Data.Height = 170;
415 
416     manage->New.Data.Cnt[0] = 0;
417     manage->New.Data.Cnt[1] = 195; /* immutable time */
418     manage->New.Data.Cnt[2] = 0; /* image counter */
419     manage->New.Data.Cnt[3] = 1; /* x move */
420     manage->New.Data.Cnt[4] = 0; /* y move */
421     manage->New.Data.Cnt[5] = 0;  /* laser counter */
422 
423     manage->New.Grp.image = Boss4Image;
424     return NewObj(MEnemy,BossAct4,BossHit1,DrawImage);
425 }
426 
BossAct4(ObjData * my)427 DelAtt BossAct4(ObjData *my)
428 {
429     if (my->Cnt[0] < my->Cnt[1])
430     {/* appears slowly */
431 	my->Y++;
432 	my->Cnt[0]++;
433 	return NoneDel;
434     }
435 
436     if (manage->BossTime <= 0)
437     {
438       if (my->Y > 0 - my->Height/2 - 100)
439         (my->Y) -= 4;
440       if (my->Y < 0 - my->Height/2 - 50)
441       {
442         if ((player->Ships <= 0) && (manage->player[0]->Data.Cnt[3] != 0))
443           return NoneDel;
444         else
445           return BossDel;
446       }
447       else
448 	return NoneDel;
449     }
450 
451     (manage->BossTime)--;
452 
453     if (my->Cnt[5] >= (8-manage->Loop))
454     {
455 	LaserShot(my->X + rand()%600-300, my->Y, 11 + rand()%3  + manage->Loop*7);
456 	LaserShot(my->X + rand()%600-300, my->Y, 6 + rand()%3 + manage->Loop*7);
457 	LaserShot(my->X + rand()%600-300, my->Y, 1 + rand()%3 + manage->Loop*7);
458 	LaserShot(my->X + rand()%600-300, my->Y, -4 + rand()%3 + manage->Loop*7);
459         if (manage->Loop >2)
460 	LaserShot(my->X + rand()%600-300, my->Y, 6 + rand()%3 + manage->Loop*7);
461         if (manage->Loop >1)
462 	LaserShot(my->X + rand()%600-300, my->Y, 1 + rand()%3 + manage->Loop*7);
463 	my->Cnt[5] = 0;
464     }
465     else
466 	my->Cnt[5]++;
467 
468     if (my->X < manage->player[0]->Data.X)
469     {
470         if (my->inertX <= 8)
471             my->inertX++;
472     }
473     if (my->X > manage->player[0]->Data.X)
474     {
475         if (my->inertX >= -8)
476             my->inertX--;
477     }
478 
479     my->X += my->inertX;
480 
481     return NoneDel;
482 }
483 
NewBoss5(void)484 int NewBoss5(void)
485 {
486     manage->New.Data.hitAtt = MEnemy;
487     manage->New.Data.hitMask = MPlayer | MPShot;
488 
489     manage->New.Data.X = FieldW/2;
490     manage->New.Data.Y = -128;
491 
492     manage->New.Data.HP = 350;
493     manage->New.Data.Point = 7000;
494     manage->New.Data.EnemyAtt = BossDel;
495 
496     manage->New.Data.Width = 120;
497     manage->New.Data.Height = 120;
498 
499     manage->New.Data.Cnt[0] = 0;
500     manage->New.Data.Cnt[1] = 200; /* immutable time */
501     manage->New.Data.Cnt[2] = 0; /* image counter */
502     manage->New.Data.Cnt[3] = manage->player[0]->Data.X; /* x move */
503     manage->New.Data.Cnt[4] = manage->player[0]->Data.Y; /* y move */
504     manage->New.Data.Cnt[5] = 0;  /* shot counter */
505     manage->New.Data.Cnt[6] = 0;  /* angle counter */
506 
507     manage->New.Grp.image = Boss5Image;
508     return NewObj(MEnemy,BossAct5,BossHit1,DrawImage);
509 }
510 
BossAct5(ObjData * my)511 DelAtt BossAct5(ObjData *my)
512 {
513   int i;
514 
515     if (my->Cnt[0] < my->Cnt[1])
516     {/* appears slowly */
517 	my->Y++;
518 	my->Cnt[0]++;
519 	return NoneDel;
520     }
521 
522     if (manage->BossTime <= 0)
523     {
524       if (my->Y > 0 - my->Height/2 - 100)
525         (my->Y) -= 4;
526       if (my->Y < 0 - my->Height/2 - 50)
527       {
528         if ((player->Ships <= 0) && (manage->player[0]->Data.Cnt[3] != 0))
529           return NoneDel;
530         else
531           return BossDel;
532       }
533       else
534 	return NoneDel;
535     }
536 
537     (manage->BossTime)--;
538 
539     if (my->Cnt[5] > 120)
540     {
541 	my->Cnt[3] = manage->player[0]->Data.X;
542 	my->Cnt[4] = manage->player[0]->Data.Y;
543 	my->Cnt[5] = 0;
544     }
545     else if (abs(my->X-my->Cnt[3]) > 5 || abs(my->Y-my->Cnt[4]) > 5)
546     {
547 	if (my->X < my->Cnt[3])
548 	{
549 	    if (my->Cnt[3]-my->X > 50)
550 		my->X += 20;
551 	    else if (my->Cnt[3]-my->X > 30)
552 		my->X += 10;
553 	    else if (my->Cnt[3]-my->X > 20)
554 		my->X += 5;
555 	    else
556 		my->X ++;
557 	}
558 	else
559 	{
560 	    if (my->X-my->Cnt[3] > 50)
561 		my->X -= 20;
562 	    else if (my->X-my->Cnt[3] > 30)
563 		my->X -= 10;
564 	    else if (my->X-my->Cnt[3] > 20)
565 		my->X -= 5;
566 	    else
567 		my->X --;
568 	}
569 
570 	if (my->Y < my->Cnt[4])
571 	{
572 	    if (my->Cnt[4]-my->Y > 50)
573 		my->Y += 20;
574 	    else if (my->Cnt[4]-my->Y > 30)
575 		my->Y += 10;
576 	    else if (my->Cnt[4]-my->Y > 20)
577 		my->Y += 5;
578 	    else
579 		my->Y ++;
580 	}
581 	else
582 	{
583 	    if (my->Y-my->Cnt[4] > 50)
584 		my->Y -= 20;
585 	    else if (my->Y-my->Cnt[4] > 30)
586 		my->Y -= 10;
587 	    else if (my->Y-my->Cnt[4] > 20)
588 		my->Y -= 5;
589 	    else
590 		my->Y --;
591 	}
592     }
593     else
594     {
595       if (manage->Loop >1)
596       {
597         if (my->Cnt[5] % 2 == 0)
598         {
599           for (i =1; i <manage->Loop; i++)
600             ShotToAngle(my->X, my->Y, rand()%360, 3);
601         }
602       }
603 
604       my->Cnt[6] += 13;
605       if (my->Cnt[6] >= 360)
606         my->Cnt[6] -= 360;
607       ShotToAngle(my->X,my->Y,my->Cnt[6],4 + manage->Loop * 4);
608 
609       my->Cnt[5]++;
610     }
611 
612     return NoneDel;
613 }
614 
NewBoss6(void)615 int NewBoss6(void)
616 {
617     manage->New.Data.hitAtt = MEnemy;
618     manage->New.Data.hitMask = MPlayer | MPShot;
619 
620     manage->New.Data.X = FieldW/2;
621     manage->New.Data.Y = -64;
622 
623     manage->New.Data.HP = 400;
624     manage->New.Data.Point = 9000;
625     manage->New.Data.EnemyAtt = BossDel;
626 
627     manage->New.Data.Width = 300;
628     manage->New.Data.Height = 100;
629 
630     manage->New.Data.Cnt[0] = 0;
631     manage->New.Data.Cnt[1] = 200; /* immutable time */
632     manage->New.Data.Cnt[2] = 0; /* image counter */
633 
634     manage->New.Data.Cnt[3] = 0; /* stealth */
635     manage->New.Data.Cnt[4] = 0;  /* shot counter */
636 
637     manage->New.Grp.image = Boss6Image;
638     return NewObj(MEnemy,BossAct6,BossHit1,DrawImage);
639 }
640 
BossAct6(ObjData * my)641 DelAtt BossAct6(ObjData *my)
642 {
643     if (my->Cnt[0] < my->Cnt[1])
644     {/* appears slowly */
645 	my->Y++;
646 	my->Cnt[0]++;
647 	return NoneDel;
648     }
649 
650     if (manage->BossTime <= 0)
651     {
652       if (my->Cnt[3] == 50)
653       {
654         if ((player->Ships <= 0) && (manage->player[0]->Data.Cnt[3] != 0))
655           return NoneDel;
656         else
657           return BossDel;
658       }
659     }
660 
661     if (manage->BossTime >= 1)
662       (manage->BossTime)--;
663 
664     if (my->Cnt[3] == 0)
665     {
666 	my->hitAtt = MEnemy;
667         my->hitMask = MPlayer | MPShot;
668 	my->image = 0;
669 	switch (my->Cnt[4]%10)
670 	{
671 	  case 0:
672 	    if (manage->Loop > 2)
673 	    {
674 		RingToPoint(my->X-128,my->Y+32,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%5+3);
675 		RingToPoint(my->X-128,my->Y+32,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%8+3);
676 		RingToPoint(my->X-128,my->Y+32,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%3+5);
677 	    }
678 	    RingToAngle(my->X-128,my->Y+32,80,8);
679 	    RingToAngle(my->X-128,my->Y+32,90,8);
680 	    RingToAngle(my->X-128,my->Y+32,100,8);
681 	    break;
682 	  case 2:
683 	    RingToAngle(my->X,my->Y+32,80,8);
684 	    RingToAngle(my->X,my->Y+32,90,8);
685 	    RingToAngle(my->X,my->Y+32,100,8);
686 	    break;
687 	  case 4:
688 	    if (manage->Loop > 2)
689 	    {
690 		RingToPoint(my->X+128,my->Y+32,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%5+3);
691 		RingToPoint(my->X+128,my->Y+32,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%8+3);
692 		RingToPoint(my->X+128,my->Y+32,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%3+5);
693 	    }
694 	    RingToAngle(my->X+128,my->Y+32,80,8);
695 	    RingToAngle(my->X+128,my->Y+32,90,8);
696 	    RingToAngle(my->X+128,my->Y+32,100,8);
697 	    break;
698 	  case 6:
699 	    HomingShot(my->X-90,my->Y-20,-15,-10);
700 	    HomingShot(my->X-60,my->Y-20,0,-10);
701 	    HomingShot(my->X+60,my->Y-20,0,-10);
702 	    HomingShot(my->X+90,my->Y-20,15,-10);
703 	    break;
704 	  case 8:
705             LaserShot(my->X-120 +rand()%240,my->Y,20);
706 	    LaserShot(my->X-120,my->Y,20);
707 	    LaserShot(my->X+120,my->Y,20);
708             if (manage->Loop == 1)
709               LaserShot(my->X, my->Y, 20);
710             else if (manage->Loop == 2)
711             {
712               LaserShot(my->X-30,my->Y,20);
713               LaserShot(my->X+30,my->Y,20);
714             }
715             else
716             {
717               LaserShot(my->X -60, my->Y, 20);
718               LaserShot(my->X, my->Y, 20);
719               LaserShot(my->X +60,my->Y,20);
720             }
721 	    break;
722 	}
723         if (manage->Loop >2)
724           if (my->Cnt[4] %2 == 0)
725             if ((manage->player[0]->Data.X < my->X -120)
726                 ||(manage->player[0]->Data.X > my->X +120)
727                 ||(manage->player[0]->Data.Y < my->Y))
728               ShotToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y, 18);
729 	my->Cnt[4]++;
730     }
731     else
732     {
733 	my->Cnt[3]--;
734 	if (my->Cnt[3] < 20)
735 	{
736 	    if (my->Cnt[3]%2 == 0)
737 		my->image = 0;
738 	    else
739 		my->image = 1;
740 	}
741     }
742 
743     if (my->Cnt[4] == 45)
744     {
745         ShotToAngle(my->X -120, my->Y, 105, 25);
746         ShotToAngle(my->X -120, my->Y, 115, 25);
747         ShotToAngle(my->X -120, my->Y, 125, 25);
748         ShotToAngle(my->X -120, my->Y, 135, 25);
749         ShotToAngle(my->X -120, my->Y, 145, 25);
750         ShotToAngle(my->X +120, my->Y, 75, 25);
751         ShotToAngle(my->X +120, my->Y, 65, 25);
752         ShotToAngle(my->X +120, my->Y, 55, 25);
753         ShotToAngle(my->X +120, my->Y, 45, 25);
754         ShotToAngle(my->X +120, my->Y, 35, 25);
755         if (manage->Loop >1)
756         {
757           ShotToAngle(my->X -120, my->Y, 155, 25);
758           ShotToAngle(my->X -120, my->Y, 165, 25);
759           ShotToAngle(my->X -120, my->Y, 175, 25);
760           ShotToAngle(my->X +120, my->Y, 25, 25);
761           ShotToAngle(my->X +120, my->Y, 15, 25);
762           ShotToAngle(my->X +120, my->Y, 5, 25);
763         }
764     }
765 
766     if (my->Cnt[4] >= 50)
767     {
768 	my->Cnt[3] = 50;
769 	my->Cnt[4] = 0;
770         my->hitAtt = 0;
771         my->hitMask = 0;
772 	my->image = 1;
773         my->showDamegeTime = 0;
774 
775         ShotToAngle(my->X -120, my->Y, 100, 25);
776         ShotToAngle(my->X -120, my->Y, 110, 25);
777         ShotToAngle(my->X -120, my->Y, 120, 25);
778         ShotToAngle(my->X -120, my->Y, 130, 25);
779         ShotToAngle(my->X -120, my->Y, 140, 25);
780         ShotToAngle(my->X +120, my->Y, 80, 25);
781         ShotToAngle(my->X +120, my->Y, 70, 25);
782         ShotToAngle(my->X +120, my->Y, 60, 25);
783         ShotToAngle(my->X +120, my->Y, 50, 25);
784         ShotToAngle(my->X +120, my->Y, 40, 25);
785         if (manage->Loop >1)
786         {
787           ShotToAngle(my->X -120, my->Y, 150, 25);
788           ShotToAngle(my->X -120, my->Y, 160, 25);
789           ShotToAngle(my->X -120, my->Y, 170, 25);
790           ShotToAngle(my->X +120, my->Y, 30, 25);
791           ShotToAngle(my->X +120, my->Y, 20, 25);
792           ShotToAngle(my->X +120, my->Y, 10, 25);
793         }
794 
795 	my->X = rand()%FieldW;
796 	my->Y = rand()%((FieldH -(FieldH%2))/2);
797     }
798 
799     return NoneDel;
800 }
801 
NewBoss7(void)802 int NewBoss7(void)
803 {
804     manage->New.Data.hitAtt = MEnemy;
805     manage->New.Data.hitMask = MPlayer | MPShot;
806 
807     manage->New.Data.HP = 150;
808     manage->New.Data.Point = 8000;
809     manage->New.Data.EnemyAtt = BossDel;
810 
811     manage->New.Data.Width = 32;
812     manage->New.Data.Height = 32;
813 
814     manage->New.Data.X = FieldW/2;
815     manage->New.Data.Y = 1 - manage->New.Data.Height/2;
816 
817     manage->New.Data.Cnt[0] = 0;
818     manage->New.Data.Cnt[1] = 0; /* appears slowly */
819     manage->New.Data.Cnt[2] = 0; /* image counter */
820 
821     do {
822 	manage->New.Data.Cnt[3] = rand()%30 - 15; /* x move */
823     }while (abs(manage->New.Data.Cnt[3]) < 5);
824     do {
825 	manage->New.Data.Cnt[4] = rand()% 10 + 5; /* y move */
826     }while (abs(manage->New.Data.Cnt[4]) < 5);
827 
828     manage->New.Data.Cnt[5] = 0;  /* shot counter */
829 
830     /* "appeared" counter */
831     manage->New.Data.Cnt[6] = 0;
832 
833     manage->New.Grp.image = EBoundImage;
834     return NewObj(MEnemy,BossAct7,BossHit1,DrawImage);
835 }
836 
BossAct7(ObjData * my)837 DelAtt BossAct7(ObjData *my)
838 {
839   int i;
840     if (manage->BossTime >= 1)
841       (manage->BossTime)--;
842 
843     my->image++;
844     if (my->image >= 8)
845         my->image = 0;
846 
847     if (manage->BossTime >= 1)
848     {
849       if (manage->Loop >1)
850       {
851         if (my->Cnt[5] % 20 == 0)
852         {
853           for (i = 0; i<360; i+= (90 - (90 % manage->Loop))/ manage->Loop)
854             ShotToAngle(my->X, my->Y, i, manage->Loop * 2);
855         }
856       }
857 
858       if (my->Cnt[5] % 30 == 0)
859       {
860         BoundShot(my->X,my->Y,rand()%30-15,rand()%30-15, 5);
861       }
862     }
863 
864 
865     (my->Cnt[5])++;
866 
867     if (my->Cnt[5] >= 60)
868       my->Cnt[5] = 0;
869 
870     if ((my->Cnt[6] != 0) && (manage->BossTime >= 1))
871     {
872       if ((my->X+my->Cnt[3]>FieldW) || (my->X+my->Cnt[3]<0))
873         my->Cnt[3] = my->Cnt[3]*(-1);
874       if ((my->Y+my->Cnt[4]>FieldH) || (my->Y+my->Cnt[4]<0))
875         my->Cnt[4] = my->Cnt[4]*(-1);
876     }
877 
878     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
879     {
880       if ((player->Ships <= 0) && (manage->player[0]->Data.Cnt[3] != 0))
881         return NoneDel;
882       else
883         return BossDel;
884     }
885     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
886     {
887       if ((player->Ships <= 0) && (manage->player[0]->Data.Cnt[3] != 0))
888         return NoneDel;
889       else
890         return BossDel;
891     }
892 
893     my->X += my->Cnt[3];
894     my->Y += my->Cnt[4];
895 
896     if ((my->Cnt[6] == 0) && (my->X >= 0) && (my->X <= FieldW)
897         && (my->Y >= 0) && (my->Y < FieldH))
898       my->Cnt[6] = 1;
899 
900     return NoneDel;
901 }
902 
NewBoss8(void)903 int NewBoss8(void)
904 {
905     manage->New.Data.hitAtt = MEnemy;
906     manage->New.Data.hitMask = MPlayer | MPShot;
907 
908     manage->New.Data.X = FieldW/2;
909     manage->New.Data.Y = -80;
910 
911     manage->New.Data.HP = 600;
912     manage->New.Data.Point = 10000;
913     manage->New.Data.EnemyAtt = BossDel;
914 
915     manage->New.Data.Width = 200;
916     manage->New.Data.Height = 180;
917 
918     manage->New.Data.Cnt[0] = 0;
919     manage->New.Data.Cnt[1] = 200; /* appears slowly */
920     manage->New.Data.Cnt[2] = 0; /* image counter */
921     manage->New.Data.Cnt[3] = 10; /* x move */
922     manage->New.Data.Cnt[4] = 0; /* y move */
923     manage->New.Data.Cnt[5] = 0;  /* shot counter */
924     manage->New.Data.Cnt[6] = rand()%4; /* mode */
925     manage->New.Data.Cnt[7] = 0; /* mode counter */
926     manage->New.Data.Cnt[8] = 0; /* after-death counter */
927 
928     manage->New.Grp.image = Boss7Image;
929     return NewObj(MEnemy,BossAct8,BossHit8,DrawImage);
930 }
931 
BossAct8(ObjData * my)932 DelAtt BossAct8(ObjData *my)
933 {
934     if (my->Cnt[0] < my->Cnt[1])
935     {/* appears slowly */
936 	my->Y++;
937 	my->Cnt[0]++;
938 	return NoneDel;
939     }
940 
941     if (my->kill == True)
942     {
943       /* the boss is dead */
944       return BossAct8_dead(my);
945     }
946 
947     /* the boss is alive */
948     if (manage->BossTime <= 0)
949     {
950       if (my->Y < 0 - my->Height/2 - 50)
951       {
952         if ((player->Ships > 0) ||(manage->player[0]->Data.Cnt[3] == 0))
953           return BossDel;
954         else
955           return NoneDel;
956       }
957       else
958       {
959         (my->Y) -= 4;
960         return NoneDel;
961       }
962     }
963 
964     (manage->BossTime)--;
965 
966     if (my->Cnt[5] > 8)
967 	my->Cnt[5] = 0;
968     else
969 	my->Cnt[5]++;
970 
971     if ((my->Cnt[5]%2==0) && ((my->Cnt[6] ==0) || (my->Cnt[6] == 2)
972                               || (my->Cnt[6] == 3)))
973     {
974 	RingToAngle(my->X, my->Y-60, rand()%50+70, rand()%15+5);
975 	RingToAngle(my->X, my->Y-60, rand()%20+80, rand()%10+10);
976         /*
977 	if (manage->Loop > 2)
978 	    RingToAngle(my->X, my->Y-60, rand()%20+80, rand()%5+15);
979         */
980     }
981 
982     if (my->Cnt[6] != 4)
983     {
984 	if (my->X>manage->player[0]->Data.X && my->X>my->HarfW)
985 	    my->X--;
986 	else if (my->X<manage->player[0]->Data.X && my->X<(FieldW-my->HarfW))
987 	    my->X++;
988     }
989 
990     if (my->Cnt[6] == 0)
991     {
992       return BossAct8_rand_shot(my);
993     }
994     else if (my->Cnt[6] == 1)
995     {
996       return BossAct8_ring_shot(my);
997     }
998     else if (my->Cnt[6] == 2)
999     {
1000       return BossAct8_bound_shot(my);
1001     }
1002     else if (my->Cnt[6] == 3)
1003     {
1004       return BossAct8_homing_shot(my);
1005     }
1006     else if (my->Cnt[6] == 4)
1007     {
1008       return BossAct8_charge_shot(my);
1009     }
1010     else if (my->Cnt[6] == 5)
1011     {
1012       return BossAct8_n_way_shot(my);
1013     }
1014 
1015     return NoneDel;
1016 }
1017 
BossHit8(ObjData * my,ObjData * your)1018 DelAtt BossHit8(ObjData *my, ObjData *your)
1019 {
1020   int temp = your->Attack;
1021     if (my->Cnt[0] < my->Cnt[1])
1022 	return NoneDel;
1023     /*
1024     if (my->Cnt[6] == 4)
1025 	return NoneDel;
1026     */
1027     /* immutable in above cases */
1028     if (my->HP < your->Attack)
1029       temp = my->HP;
1030 
1031     my->HP -= temp;
1032     player->Rec[0].score += temp;
1033 
1034     if (my->HP <= 0)
1035     {
1036        player->Rec[0].score -= 1;
1037        my->showDamegeTime = 0;
1038 
1039        my->kill = True;
1040     }
1041     else
1042     {
1043       my->showDamegeTime = 15;
1044     }
1045 
1046     return NoneDel;
1047 }
1048 
BossAct8_dead(ObjData * my)1049 static DelAtt BossAct8_dead(ObjData *my)
1050 {
1051   int i;
1052   int j;
1053   /* the boss is dead */
1054   NewLargeBomb(my->X+rand()%230-115,my->Y+rand()%180-90);
1055   NewLargeBomb(my->X+rand()%230-115,my->Y+rand()%180-90);
1056 
1057   my->Cnt[8]++;
1058   if ((player->Ships <= 0) && (manage->player[0]->Data.Cnt[3] != 0))
1059     if (my->Cnt[8] >= 300)
1060       my->Cnt[8] = 0;
1061 
1062   if (my->Cnt[8] %3 == 0)
1063   {
1064     if (my->X > manage->player[0]->Data.X)
1065       (my->X)--;
1066     else if (my->X < manage->player[0]->Data.X)
1067       (my->X)++;
1068     if (my->Y > manage->player[0]->Data.Y)
1069       (my->Y)--;
1070     else if (my->Y < manage->player[0]->Data.Y)
1071       (my->Y)++;
1072   }
1073 
1074   if (my->Cnt[8] %30 == 0)
1075   {
1076     for (i=0; i<24; i++)
1077       ShotToAngle(my->X,my->Y,i*15, 7);
1078   }
1079   else if (my->Cnt[8] %30 == 15)
1080   {
1081     for (i=0; i<24; i++)
1082       ShotToAngle(my->X,my->Y,i*15 + 7,7);
1083   }
1084   if (my->Cnt[8] %13 == 0)
1085   {
1086     ShotToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y, manage->Loop *5);
1087     if (manage->Loop >2)
1088     {
1089       BoundShot(my->X, my->Y-60,rand()%20-10,rand()%4+10,4);
1090     }
1091   }
1092   if (my->Cnt[8] %5 == 0)
1093   {
1094     if (manage->Loop >1)
1095     {
1096       for (i=1; i< manage->Loop * 3; i++)
1097         ShotToAngle(my->X,my->Y,rand()%360, manage->Loop *3);
1098     }
1099   }
1100 
1101   if (my->Cnt[8] >= 300)
1102   {
1103     for (i=0; i<=10; i++)
1104       for (j=0; j<=10; j++)
1105         NewLargeBomb(50*i,65*j);
1106     return my->EnemyAtt;
1107   }
1108   else
1109     return NoneDel;
1110 }
1111 
BossAct8_rand_shot(ObjData * my)1112 static DelAtt BossAct8_rand_shot(ObjData *my)
1113 {
1114   int i;
1115   if (my->Cnt[7]% 10 == 0)
1116   {
1117     for (i = 1; i <= manage->Loop; i++)
1118     {
1119       ShotToAngle(my->X-60, my->Y-60, rand()%50 + 70, rand()%5+5);
1120       ShotToAngle(my->X+60, my->Y-60, rand()%50 + 70, rand()%5+5);
1121     }
1122     ShotToPoint(my->X,my->Y-60,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%5+3);
1123   }
1124 
1125   BossAct8_next(my, 100);
1126   return NoneDel;
1127 }
1128 
BossAct8_ring_shot(ObjData * my)1129 static DelAtt BossAct8_ring_shot(ObjData *my)
1130 {
1131   if (my->Cnt[7]%2 == 0)
1132   {
1133     RingToPoint(my->X-60, my->Y+10, manage->player[0]->Data.X,manage->player[0]->Data.Y, rand()%10 + 20);
1134     RingToPoint(my->X+60, my->Y+10, manage->player[0]->Data.X,manage->player[0]->Data.Y, rand()%10 + 20);
1135     if (manage->Loop >1)
1136     {
1137       RingToAngle(my->X, my->Y - 60, 90, rand()%10 + 20);
1138       RingToAngle(my->X, my->Y - 60, 90, rand()%10 + 20);
1139     }
1140     if (manage->Loop >2)
1141     {
1142       RingToAngle(my->X-60, my->Y - 60, 90, rand()%10 + 20);
1143       RingToAngle(my->X+60, my->Y - 60, 90, rand()%10 + 20);
1144     }
1145   }
1146 
1147   BossAct8_next(my, 70);
1148   return NoneDel;
1149 }
1150 
BossAct8_bound_shot(ObjData * my)1151 static DelAtt BossAct8_bound_shot(ObjData *my)
1152 {
1153   if (manage->Loop <=2)
1154   {
1155     if (my->Cnt[7]  % 16 == 0)
1156       BoundShot(my->X+60,my->Y-60,rand()%20-10,rand()%4+10,2);
1157     else if (my->Cnt[7]  % 16 == 8)
1158       BoundShot(my->X-60,my->Y-60,rand()%20-10,rand()%4+10,2);
1159   }
1160   else
1161   {
1162     if (my->Cnt[7]  % 16 == 0)
1163       BoundShot(my->X+60,my->Y-60, (rand()%20-10)*2, (rand()%4+10)*2, 2);
1164     else if (my->Cnt[7]  % 16 == 8)
1165       BoundShot(my->X-60,my->Y-60, (rand()%20-10)*2 ,(rand()%4+10)*2, 2);
1166   }
1167 
1168   BossAct8_next(my, 100);
1169   return NoneDel;
1170 }
1171 
BossAct8_homing_shot(ObjData * my)1172 static DelAtt BossAct8_homing_shot(ObjData *my)
1173 {
1174   if (my->Cnt[7] %8 == 0)
1175   {
1176     HomingShot(my->X-60,my->Y-10,-10, 5);
1177     HomingShot(my->X+60,my->Y-10, 10, 5);
1178     if (manage->Loop > 2)
1179     {
1180       HomingShot(my->X-60,my->Y-10,-3, 10);
1181       HomingShot(my->X+60,my->Y-10, 3, 10);
1182     }
1183   }
1184 
1185   BossAct8_next(my, 100);
1186   return NoneDel;
1187 }
1188 
BossAct8_charge_shot(ObjData * my)1189 static DelAtt BossAct8_charge_shot(ObjData *my)
1190 {
1191   int i;
1192   if (my->Cnt[7] == 48 - manage->Loop *8)
1193   {
1194     for (i=0; i<24; i++)
1195       ShotToAngle(my->X,my->Y,i*15,15);
1196   }
1197   if (my->Cnt[7] == 53 - manage->Loop *8)
1198   {
1199     for (i=0; i<24; i++)
1200       ShotToAngle(my->X,my->Y,i*15+7,20);
1201   }
1202   if (my->Cnt[7] > 53 - manage->Loop *8)
1203   {
1204     LaserShot(my->X-120,my->Y-60,35);
1205     LaserShot(my->X-80 ,my->Y-60,35);
1206     LaserShot(my->X-40 ,my->Y-60,35);
1207     LaserShot(my->X    ,my->Y-60,35);
1208     LaserShot(my->X+40 ,my->Y-60,35);
1209     LaserShot(my->X+80 ,my->Y-60,35);
1210     LaserShot(my->X+120,my->Y-60,35);
1211   }
1212 
1213   BossAct8_next(my, 58 - manage->Loop *8);
1214   return NoneDel;
1215 }
1216 
BossAct8_n_way_shot(ObjData * my)1217 static DelAtt BossAct8_n_way_shot(ObjData *my)
1218 {
1219   int xtemp;
1220   int ytemp;
1221   int speedtemp;
1222   if (my->Cnt[7] % 13 == 0)
1223   {
1224     xtemp = rand()%FieldW;
1225     ytemp = rand()%((FieldH -(FieldH%2))/2);
1226     speedtemp = rand()%7 + 5;
1227 
1228     if (manage->Loop == 1)
1229     {
1230       ShotToAngle(xtemp, ytemp, 50, speedtemp);
1231       ShotToAngle(xtemp, ytemp, 70, speedtemp);
1232       ShotToAngle(xtemp, ytemp, 90, speedtemp);
1233       ShotToAngle(xtemp, ytemp, 110, speedtemp);
1234       ShotToAngle(xtemp, ytemp, 130, speedtemp);
1235     }
1236     else if (manage->Loop == 2)
1237     {
1238       ShotToAngle(xtemp, ytemp, 51, speedtemp);
1239       ShotToAngle(xtemp, ytemp, 64, speedtemp);
1240       ShotToAngle(xtemp, ytemp, 77, speedtemp);
1241       ShotToAngle(xtemp, ytemp, 90, speedtemp);
1242       ShotToAngle(xtemp, ytemp, 103, speedtemp);
1243       ShotToAngle(xtemp, ytemp, 116, speedtemp);
1244       ShotToAngle(xtemp, ytemp, 129, speedtemp);
1245     }
1246     else
1247     {
1248       ShotToAngle(xtemp, ytemp, 50, speedtemp);
1249       ShotToAngle(xtemp, ytemp, 60, speedtemp);
1250       ShotToAngle(xtemp, ytemp, 70, speedtemp);
1251       ShotToAngle(xtemp, ytemp, 80, speedtemp);
1252       ShotToAngle(xtemp, ytemp, 90, speedtemp);
1253       ShotToAngle(xtemp, ytemp, 100, speedtemp);
1254       ShotToAngle(xtemp, ytemp, 110, speedtemp);
1255       ShotToAngle(xtemp, ytemp, 120, speedtemp);
1256       ShotToAngle(xtemp, ytemp, 130, speedtemp);
1257     }
1258   }
1259 
1260   BossAct8_next(my, 150);
1261   return NoneDel;
1262 }
1263 
BossAct8_next(ObjData * my,int span)1264 static void BossAct8_next(ObjData *my, int span)
1265 {
1266   int modetemp = 0;
1267   if (my->Cnt[7] > span)
1268   {
1269     do
1270     {
1271       modetemp = rand()%6;
1272     }while (modetemp == my->Cnt[6]);
1273     my->Cnt[6] = modetemp;
1274     my->Cnt[7] = 0;
1275   }
1276   else
1277     my->Cnt[7]++;
1278 }
1279