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: enemy.c,v 1.16 2002/04/29 03:40:19 oohara Exp $ */
8 
9 /* rand */
10 #include <stdlib.h>
11 /* abs */
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 "enemy.h"
26 #include "extern.h"
27 #include "sin.h"
28 
29 /* definition of objects
30  * - initialization function
31  * - action function
32  * - hit function
33  *
34  * initialization add action function and display/hit function to the table
35  */
36 
37 /* run straight ahead */
NewEnemy1(int x,int y)38 int NewEnemy1(int x, int y)
39 {
40   /* attribute of this object */
41     manage->New.Data.hitAtt = MEnemy;
42     /* what objects should hit this object */
43     manage->New.Data.hitMask = MPlayer | MPShot;
44 
45     manage->New.Data.HP = 1;
46     manage->New.Data.Point = 100;
47     manage->New.Data.EnemyAtt = ZakoDel;
48 
49     /* size for collision detection */
50     manage->New.Data.Width = 32;
51     manage->New.Data.Height = 32;
52 
53     manage->New.Data.X = x;
54     manage->New.Data.Y = 1 - manage->New.Data.Height/2;
55 
56     manage->New.Data.Angle = 0;
57     manage->New.Data.Speed = rand()%15 + 1;
58 
59     manage->New.Data.Cnt[0] = 0;
60 
61     /* pixmap for this object */
62     manage->New.Grp.image = Enemy1Image;
63 
64     /* add action function and hit function to the table */
65     return NewObj(MEnemy,EnemyAct1,EnemyHit1,DrawImage);
66 }
67 
EnemyAct1(ObjData * my)68 DelAtt EnemyAct1(ObjData *my)
69 {
70   int i;
71     if (manage->Loop > 1)
72     {
73       /* shoot in loop 2 or later */
74 	if (my->shotTime >= ShotTiming)
75 	{
76           for (i =1; i< manage->Loop; i++)
77 	    ShotToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,5);
78 	    my->shotTime = my->startTime;
79 	}
80 	else
81 	    my->shotTime++;
82     }
83 
84     my->image = 4;
85     my->Y += my->Speed;
86 
87     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
88 	return NullDel;
89     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
90 	return NullDel;
91 
92     return NoneDel;
93 }
94 
95 /* may give you an item */
EnemyHit1(ObjData * my,ObjData * your)96 DelAtt EnemyHit1(ObjData *my, ObjData *your)
97 {
98   int temp = your->Attack;
99     if (my->HP < your->Attack)
100       temp = my->HP;
101 
102     my->HP -= temp;
103     player->Rec[0].score += temp;
104 
105     if (my->HP <= 0)
106     {
107       player->Rec[0].score -= 1;
108 
109       /* always gives you a shot in loop 3 or later */
110 	if (manage->Loop > 2)
111 	    ShotToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,5);
112 
113 	if (rand()%100 < 20)
114 	    NewEnemy10(my->X,my->Y);
115         NewBomb(my->X,my->Y);
116 
117         my->showDamegeTime = 0;
118         return my->EnemyAtt;
119     }
120     else
121     {
122       my->showDamegeTime = 15;
123       return NoneDel;
124     }
125 
126 }
127 
128 /* codename "sine curve" (in fact it is a parabola) */
NewEnemy2(int x,int y)129 int NewEnemy2(int x, int y)
130 {
131 
132     manage->New.Data.hitAtt = MEnemy;
133     manage->New.Data.hitMask = MPlayer | MPShot;
134 
135     manage->New.Data.HP = 1;
136     manage->New.Data.Point = 100;
137     manage->New.Data.EnemyAtt = ZakoDel;
138 
139     manage->New.Data.Width = 32;
140     manage->New.Data.Height = 32;
141 
142     manage->New.Data.X = x;
143     manage->New.Data.Y = 1 - manage->New.Data.Height/2;
144 
145     manage->New.Data.inertX = 0;
146     manage->New.Data.inertY = 1;
147 
148     manage->New.Data.Angle = 0;
149     manage->New.Data.Speed = 0;
150     manage->New.Data.Cnt[0] = 0;
151     /* range of x */
152     manage->New.Data.Cnt[1] = rand()%3 + 5;
153     if (x < FieldW/2)
154 	manage->New.Data.Cnt[2] = 0;
155     else
156 	manage->New.Data.Cnt[2] = 1;
157 
158     manage->New.Data.Cnt[3] = 0;
159 
160     manage->New.Grp.image = Enemy3Image;
161 
162     return NewObj(MEnemy,EnemyAct2,DamageHit,DrawImage);
163 }
164 
EnemyAct2(ObjData * my)165 DelAtt EnemyAct2(ObjData *my)
166 {
167     if (my->shotTime >= ShotTiming)
168     {
169 	if (manage->Loop > 1)
170 	    LaserShot(my->X,my->Y,10);
171         ShotToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,4);
172 	my->shotTime = my->startTime;
173     }
174     else
175 	my->shotTime++;
176 
177     if (my->Cnt[2] == 0)
178     {
179         my->Cnt[3]++;
180 
181         if(my->Cnt[3] >= 2*my->Cnt[1])
182             my->Cnt[2] = 1;
183     }
184     else if (my->Cnt[2] == 1)
185     {
186         my->Cnt[3]--;
187 
188         if(my->Cnt[3] <= -2*my->Cnt[1])
189             my->Cnt[2] = 0;
190     }
191 
192     my->Y += my->Cnt[1];
193     my->X += my->Cnt[3];
194 
195     /* what number of pixmap we use */
196     if (my->Cnt[3] > my->Cnt[1])
197         my->image = 2;
198     else if (my->Cnt[3] > 0)
199         my->image = 3;
200     else if (my->Cnt[3] < -my->Cnt[1])
201         my->image = 6;
202     else if(my->Cnt[3] < 0)
203         my->image = 5;
204     else
205         my->image = 0;
206 
207     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
208 	return NullDel;
209 
210     return NoneDel;
211 }
212 
213 /* turns left/right */
NewEnemy3(int x,int y)214 int NewEnemy3(int x, int y)
215 {
216 
217     manage->New.Data.hitAtt = MEnemy;
218     manage->New.Data.hitMask = MPlayer | MPShot;
219 
220     manage->New.Data.HP = 2;
221     manage->New.Data.Point = 150;
222     manage->New.Data.EnemyAtt = ZakoDel;
223 
224     manage->New.Data.Width = 32;
225     manage->New.Data.Height = 32;
226 
227     manage->New.Data.X = x;
228     manage->New.Data.Y = 1 - manage->New.Data.Height/2;
229 
230     manage->New.Data.Cnt[0] = 0;
231     manage->New.Data.Cnt[1] = 0;
232     manage->New.Data.Cnt[2] = 5;
233 
234     manage->New.Grp.image = Enemy1Image;
235     return NewObj(MEnemy,EnemyAct3,EnemyHit1,DrawImage);
236 }
237 
EnemyAct3(ObjData * my)238 DelAtt EnemyAct3(ObjData *my)
239 {
240     if (my->shotTime >= ShotTiming)
241     {
242         ShotToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,4);
243         my->shotTime = my->startTime;
244     }
245     else
246         my->shotTime++;
247 
248     if (my->Cnt[0] == 0)
249     {
250 	if (my->Y<manage->player[0]->Data.Y+10 && my->Y>manage->player[0]->Data.Y-10)
251 	{
252 	    if (my->X < manage->player[0]->Data.X)
253             {
254               my->Cnt[0] = 1;
255               if (manage->Loop >2)
256                 BoundShot(my->X, my->Y, rand()%30-15, rand()%30-15, 3);
257             }
258 
259 	    if (my->X > manage->player[0]->Data.X)
260             {
261               my->Cnt[0] = 2;
262               if (manage->Loop >2)
263                 BoundShot(my->X, my->Y, rand()%30-15, rand()%30-15, 3);
264             }
265 	}
266     }
267 
268     if (my->Cnt[0] == 0)
269     {
270 	my->Y += 2 + manage->Loop * 3;
271 	my->image = 4;
272     }
273     else if (my->Cnt[0] == 1)
274     {
275 	my->X += 15;
276 	my->image = 2;
277     }
278     else if (my->Cnt[0] == 2)
279     {
280 	my->X -= 15;
281 	my->image = 6;
282     }
283 
284     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
285 	return NullDel;
286     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
287 	return NullDel;
288 
289     return NoneDel;
290 }
291 
292 /* chases you */
NewEnemy4(int x,int y)293 int NewEnemy4(int x, int y)
294 {
295 
296     manage->New.Data.hitAtt = MEnemy;
297     manage->New.Data.hitMask = MPlayer | MPShot;
298 
299     manage->New.Data.HP = 2;
300     manage->New.Data.Point = 150;
301     manage->New.Data.EnemyAtt = ZakoDel;
302 
303     manage->New.Data.Width = 32;
304     manage->New.Data.Height = 32;
305 
306     manage->New.Data.X = x;
307     manage->New.Data.Y = 1 - manage->New.Data.Height/2;
308 
309     manage->New.Data.inertX = 0;
310     manage->New.Data.inertY = 0;
311 
312     manage->New.Grp.image = Enemy2Image;
313     return NewObj(MEnemy,EnemyAct4,DamageHit,DrawImage);
314 }
315 
EnemyAct4(ObjData * my)316 DelAtt EnemyAct4(ObjData *my)
317 {
318     if (my->shotTime >= ShotTiming)
319     {
320         ShotToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,4);
321         if (manage->Loop >1)
322         {
323           ShotToAngle(my->X, my->Y, 90, 4);
324           ShotToAngle(my->X, my->Y, 90, 8);
325           ShotToAngle(my->X, my->Y, 90, 12);
326           ShotToAngle(my->X, my->Y, 90, 16);
327         }
328 
329 	my->shotTime = my->startTime;
330     }
331     else
332 	my->shotTime++;
333 
334     if (my->X < manage->player[0]->Data.X)
335     {
336       if (my->inertX <= 8)
337         my->inertX++;
338     }
339     else if (my->X > manage->player[0]->Data.X)
340     {
341       if (my->inertX >= -8)
342         my->inertX--;
343     }
344 
345     if (my->Y < manage->player[0]->Data.Y)
346     {
347       if (my->inertY <= 8)
348         my->inertY++;
349     }
350     else if (my->Y > manage->player[0]->Data.Y)
351     {
352       if (my->inertY >= -8)
353         my->inertY--;
354     }
355 
356     my->X += my->inertX;
357     my->Y += my->inertY;
358 
359     my->image = GetDirection(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y);
360 
361     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
362 	return NullDel;
363     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
364 	return NullDel;
365 
366     return NoneDel;
367 }
368 
369 /* bounce on the left/right side of the window */
NewEnemy5(int x,int y)370 int NewEnemy5(int x, int y)
371 {
372 
373     manage->New.Data.hitAtt = MEnemy;
374     manage->New.Data.hitMask = MPlayer | MPShot;
375 
376     if (x > FieldW/2)
377     {
378 	manage->New.Data.X = FieldW;
379 	manage->New.Data.Cnt[0] = - (rand()%10 + 15);
380     }
381     else
382     {
383 	manage->New.Data.X = 0;
384 	manage->New.Data.Cnt[0] = rand()%10 + 15;
385     }
386 
387     manage->New.Data.HP = 9;
388     manage->New.Data.Point = 200;
389     manage->New.Data.EnemyAtt = ZakoDel;
390 
391     manage->New.Data.Width = 32;
392     manage->New.Data.Height = 32;
393 
394     manage->New.Data.Y = 1 - manage->New.Data.Height/2;
395 
396     manage->New.Data.inertX = 0;
397     manage->New.Data.inertY = 0;
398 
399     manage->New.Grp.image = Enemy5Image;
400     return NewObj(MEnemy,EnemyAct5,EnemyHit1,DrawImage);
401 }
402 
EnemyAct5(ObjData * my)403 DelAtt EnemyAct5(ObjData *my)
404 {
405     if (my->Cnt[0] < 0)
406     {
407 	my->inertX++;
408 	if (abs(my->inertX+my->Cnt[0]) < 5)
409 	    my->image = 3;
410 	else
411 	    my->image = 2;
412     }
413     else
414     {
415 	my->inertX--;
416 	if (abs(my->inertX+my->Cnt[0]) < 5)
417 	    my->image = 1;
418 	else
419 	    my->image = 0;
420     }
421 
422     if (my->Cnt[0]+my->inertX == 0)
423     {
424 	RingToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%4+2);
425 	RingToAngle(my->X, my->Y, 45, 5);
426 	RingToAngle(my->X, my->Y, 90, 5);
427 	RingToAngle(my->X, my->Y, 135, 5);
428 	RingToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%2+4);
429 	if (manage->Loop > 1)
430 	{
431 	    RingToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%3+3);
432 	    RingToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%4+4);
433 	}
434     }
435 
436     my->X += (my->Cnt[0] + my->inertX);
437     my->Y += 5;
438 
439     if ((my->X < 0) || (my->X > FieldW))
440 	my->inertX = 0;
441 
442     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
443 	return NullDel;
444 
445     return NoneDel;
446 }
447 
448 /* bounce on any side of the window */
NewEnemy6(int x,int y)449 int NewEnemy6(int x, int y)
450 {
451 
452     manage->New.Data.hitAtt = MEnemy;
453     manage->New.Data.hitMask = MPlayer | MPShot;
454 
455     manage->New.Data.HP = 4;
456     manage->New.Data.Point = 200;
457     manage->New.Data.EnemyAtt = ZakoDel;
458 
459     manage->New.Data.Width = 32;
460     manage->New.Data.Height = 32;
461 
462     manage->New.Data.X = x;
463     manage->New.Data.Y = 1 - manage->New.Data.Height/2;
464 
465     if (x > FieldW/2)
466 	manage->New.Data.inertX = rand()%5 + 10;
467     else
468 	manage->New.Data.inertX = rand()%5 - 15;
469 
470     manage->New.Data.inertY = rand()%10 + 5;
471 
472     manage->New.Data.Cnt[0] = 0;
473     manage->New.Data.Cnt[1] = 8;
474     /* "appeared" counter */
475     manage->New.Data.Cnt[2] = 0;
476 
477     manage->New.Grp.image = Enemy4Image;
478     return NewObj(MEnemy,EnemyAct6,DamageHit,DrawImage);
479 }
480 
EnemyAct6(ObjData * my)481 DelAtt EnemyAct6(ObjData *my)
482 {
483     if (my->shotTime >= ShotTiming)
484     {
485 	ShotToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%4+ manage->Loop * 7 -5);
486 	my->shotTime = my->startTime;
487     }
488     else
489 	my->shotTime++;
490 
491     if ((my->Cnt[2] != 0) && (my->Cnt[0] <= my->Cnt[1]))
492     {
493       if ((my->X+my->inertX>FieldW) || (my->X+my->inertX<0))
494       {
495         my->inertX = my->inertX*(-1);
496         my->Cnt[0]++;
497       }
498       if ((my->Y+my->inertY>FieldH) || (my->Y+my->inertY<0))
499       {
500         my->inertY = my->inertY*(-1);
501         my->Cnt[0]++;
502       }
503     }
504 
505     my->image++;
506     if (my->image > 7)
507 	my->image = 0;
508 
509     my->X += my->inertX;
510     my->Y += my->inertY;
511 
512     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
513 	return NullDel;
514     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
515 	return NullDel;
516 
517     if ((my->Cnt[2] == 0) && (my->X >= 0) && (my->X <= FieldW)
518         && (my->Y >= 0) && (my->Y < FieldH))
519       my->Cnt[2] = 1;
520 
521     return NoneDel;
522 }
523 
524 /* appears from the lower side of the window */
NewEnemy7(int x,int y)525 int NewEnemy7(int x, int y)
526 {
527 
528     manage->New.Data.hitAtt = MEnemy;
529     manage->New.Data.hitMask = MPlayer | MPShot;
530 
531     if (x > FieldW/2)
532 	manage->New.Data.X = FieldW -50;
533     else
534 	manage->New.Data.X =         50;
535 
536     manage->New.Data.HP = 3;
537     manage->New.Data.Point = 250;
538     manage->New.Data.EnemyAtt = ZakoDel;
539 
540     manage->New.Data.Width = 32;
541     manage->New.Data.Height = 32;
542 
543     manage->New.Data.Y = FieldH - 1 + manage->New.Data.Height/2;
544 
545     manage->New.Data.Cnt[1] = 0;
546 
547     manage->New.Grp.image = Enemy3Image;
548 
549     return NewObj(MEnemy,EnemyAct7,EnemyHit1,DrawImage);
550 }
551 
EnemyAct7(ObjData * my)552 DelAtt EnemyAct7(ObjData *my)
553 {
554     if (manage->Loop > 1)
555     {
556 	if (my->shotTime >= ShotTiming)
557 	{
558 	    HomingShot(my->X,my->Y,0,0);
559 	    my->shotTime = my->startTime;
560 	}
561 	else
562 	    my->shotTime++;
563     }
564 
565     if (my->Cnt[1] > 20)
566     {
567 	my->Y -= 9;
568 	my->image = 0;
569     }
570     else if (my->Y > FieldH-100)
571     {
572 	my->Y -= 6;
573 	my->image = 0;
574     }
575     else
576     {
577 	my->Cnt[1]++;
578 	my->image++;
579 	if (my->image > 7)
580 	    my->image = 0;
581     }
582 
583     if (my->Cnt[1] == 20)
584     {
585         ShotToAngle(my->X, my->Y, 144, 10);
586         ShotToAngle(my->X, my->Y, 180, 10);
587         ShotToAngle(my->X, my->Y, 216, 10);
588         ShotToAngle(my->X, my->Y, 252, 10);
589         ShotToAngle(my->X, my->Y, 288, 10);
590         ShotToAngle(my->X, my->Y, 324, 10);
591         ShotToAngle(my->X, my->Y, 360, 10);
592         ShotToAngle(my->X, my->Y, 36, 10);
593     }
594 
595     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
596 	return NullDel;
597     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
598 	return NullDel;
599 
600     return NoneDel;
601 }
602 
603 /* run straight ahead and shoot homing missiles */
NewEnemy8(int x,int y)604 int NewEnemy8(int x, int y)
605 {
606 
607     manage->New.Data.hitAtt = MEnemy;
608     manage->New.Data.hitMask = MPlayer | MPShot;
609 
610     manage->New.Data.HP = 15;
611     manage->New.Data.Point = 500;
612     manage->New.Data.EnemyAtt = ZakoDel;
613 
614     manage->New.Data.Width = 40;
615     manage->New.Data.Height = 50;
616 
617     manage->New.Data.X = x;
618     manage->New.Data.Y = 1 - manage->New.Data.Height/2;
619 
620     manage->New.Data.Angle = 0;
621     manage->New.Data.Speed = rand()%5 + 1;
622 
623     manage->New.Grp.image = Enemy7Image;
624 
625     return NewObj(MEnemy,EnemyAct8,LargeDamageHit,DrawImage);
626 }
627 
EnemyAct8(ObjData * my)628 DelAtt EnemyAct8(ObjData *my)
629 {
630     if (my->shotTime >= ShotTiming)
631     {
632         HomingShot(my->X+10,my->Y-20,-10,-5);
633         HomingShot(my->X-10,my->Y-20,10,-5);
634 
635 	if (manage->Loop > 1)
636 	{
637 	    LaserShot(my->X-15,my->Y-20,10);
638 	    LaserShot(my->X+15,my->Y-20,10);
639 	}
640 	my->shotTime = my->startTime;
641     }
642     else
643 	my->shotTime++;
644 
645     my->Y += my->Speed;
646 
647     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
648 	return NullDel;
649     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
650 	return NullDel;
651 
652     return NoneDel;
653 }
654 
655 /* "reversed" parabola */
NewEnemy9(int x,int y)656 int NewEnemy9(int x, int y)
657 {
658     manage->New.Data.hitAtt = MEnemy;
659     manage->New.Data.hitMask = MPlayer | MPShot;
660 
661     manage->New.Data.HP = 6;
662     manage->New.Data.Point = 300;
663     manage->New.Data.EnemyAtt = ZakoDel;
664 
665     manage->New.Data.Width = 32;
666     manage->New.Data.Height = 32;
667 
668     manage->New.Data.X = x;
669     manage->New.Data.Y = 1 - manage->New.Data.Height/2;
670 
671     if (x > FieldW/2)
672 	manage->New.Data.inertX = -(rand()%10+1);
673     else
674 	manage->New.Data.inertX = rand()%10+1;
675     manage->New.Data.inertY = rand()%10 + 15;
676 
677     manage->New.Data.Cnt[0] = 0;
678 
679     manage->New.Grp.image = Enemy6Image;
680     return NewObj(MEnemy,EnemyAct9,DamageHit,DrawImage);
681 }
682 
EnemyAct9(ObjData * my)683 DelAtt EnemyAct9(ObjData *my)
684 {
685     if (manage->Loop > 2)
686     {
687 	if (my->shotTime >= ShotTiming)
688 	{
689 	    ShotToAngle(my->X, my->Y, 50, 25);
690 	    ShotToAngle(my->X, my->Y, 70, 25);
691 	    ShotToAngle(my->X, my->Y, 90, 25);
692 	    ShotToAngle(my->X, my->Y, 110, 25);
693 	    ShotToAngle(my->X, my->Y, 130, 25);
694 	    my->shotTime = my->startTime;
695 	}
696 	else
697 	    my->shotTime++;
698     }
699 
700     if (my->inertY<0 && my->inertY%2)
701         ShotToPoint(my->X,my->Y,manage->player[0]->Data.X,manage->player[0]->Data.Y,rand()%3+3);
702 
703     my->inertY--;
704 
705     my->X += my->inertX;
706     my->Y += my->inertY;
707 
708     if (my->inertY > 10)
709 	my->image = 0;
710     else if (my->inertY > 5)
711 	my->image = 1;
712     else if (my->inertY > 0)
713 	my->image = 2;
714     else if (my->inertY > -5)
715 	my->image = 3;
716     else if (my->inertY > -10)
717 	my->image = 4;
718     else
719 	my->image = 5;
720 
721     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
722 	return NullDel;
723     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
724 	return NullDel;
725 
726     return NoneDel;
727 }
728 
729 /* power-up item */
NewEnemy10(int x,int y)730 int NewEnemy10(int x, int y)
731 {
732     manage->New.Data.hitAtt = MItem;
733     manage->New.Data.hitMask = MPlayer;
734 
735     manage->New.Data.X = x;
736     manage->New.Data.Y = y;
737 
738     manage->New.Data.HP = 0;
739     manage->New.Data.Point = 0;
740     manage->New.Data.EnemyAtt = NoneDel;
741 
742     manage->New.Data.Width = 32;
743     manage->New.Data.Height = 32;
744 
745     manage->New.Data.inertY = -10 - rand() % 10;
746 
747     /* item counter */
748     manage->New.Data.Cnt[0] = 0;
749     /* time counter */
750     manage->New.Data.Cnt[1] = 0;
751     /* max speed */
752     manage->New.Data.Cnt[2] = rand()%6 + 1;
753     if (rand()%100 < 30)
754     {
755 	manage->New.Data.Cnt[3] = 1;
756 	manage->New.Data.Cnt[0] = 1;
757     }
758     else
759 	manage->New.Data.Cnt[3] = 0;
760 
761     manage->New.Grp.image = ItemImage;
762     return NewObj(MEnemy,EnemyAct10,NullDelHit,DrawImage);
763 }
764 
EnemyAct10(ObjData * my)765 DelAtt EnemyAct10(ObjData *my)
766 {
767     my->Cnt[1]++;
768 
769     if (my->inertY < my->Cnt[2])
770 	my->inertY++;
771     my->Y += my->inertY;
772 
773     if (my->Cnt[3] == 1)
774     {
775 	if (my->Cnt[1]%25 == 0)
776 	{
777 	    if (my->Cnt[0] < 3)
778 		my->Cnt[0]++;
779 	    else
780 		my->Cnt[0] = 1;
781 	}
782     }
783 
784     my->image = my->Cnt[0];
785 
786     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
787 	return NullDel;
788     if (my->Y > FieldH + my->Height/2)
789 	return NullDel;
790 
791     return NoneDel;
792 }
793