1 //
2 //   demon.c
3 //
4 //   Copyright 2007, 2008 Lancer-X/ASCEAI
5 //
6 //   This file is part of Meritous.
7 //
8 //   Meritous is free software: you can redistribute it and/or modify
9 //   it under the terms of the GNU General Public License as published by
10 //   the Free Software Foundation, either version 3 of the License, or
11 //   (at your option) any later version.
12 //
13 //   Meritous is distributed in the hope that it will be useful,
14 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //   GNU General Public License for more details.
17 //
18 //   You should have received a copy of the GNU General Public License
19 //   along with Meritous.  If not, see <http://www.gnu.org/licenses/>.
20 //
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <math.h>
25 #include <SDL.h>
26 #include <SDL_image.h>
27 #include <assert.h>
28 
29 #include "levelblit.h"
30 #include "mapgen.h"
31 #include "save.h"
32 #include "audio.h"
33 #include "boss.h"
34 #include "tiles.h"
35 
36 SDL_Surface *reticle;
37 SDL_Surface *inrange;
38 SDL_Surface *invis_enemy;
39 
40 int searched[3000];
41 int searchdist[3000];
42 int csearch;
43 int room_active[3000];
44 
45 int fc_open = 0;
46 
47 int max_activate_dist = 0;
48 
49 // enemy
50 
sqr(int x)51 int sqr(int x)
52 {
53 	return x*x;
54 }
55 
56 struct enemy {
57 	int x, y;
58 	int room;
59 	int lives;
60 	int deaths;
61 	int str;
62 	int curr_follow;
63 
64 	int followdepth;
65 
66 	int enemy_type;
67 
68 	SDL_Surface *image;
69 	int blit_pos;
70 
71 	int creationcost;
72 
73 	int teleport_v;
74 	int speed;
75 	int t;
76 	int active;
77 	int fire_rate;
78 
79 	int last_room;
80 	int p_last_room;
81 
82 	float move_dir;
83 
84 	int min_gems;
85 	int max_gems;
86 
87 	struct enemy *next;
88 	struct enemy *next_active;
89 
90 	int delete_me;
91 	int dying;
92 
93 	struct RoomConnection *m_exit;
94 };
95 
96 // shot
97 
98 struct bullet {
99 	float x, y;
100 	struct enemy *firer;
101 	struct bullet *parent;
102 	int room;
103 	float speed;
104 	float dir;
105 	int img;
106 	// img:	0 = bullet
107 	//		1 = star
108 	//		2 = laser
109 	// 		3 = ministar
110 	//		4 = rocket
111 	//		5 = replishot
112 	//		6 = laserstar
113 	//		7 = proxy
114 	//		8 = remote laser
115 	int t;
116 
117 	int invuln;
118 	float natural_dir;
119 
120 	int fire_time;
121 	int duration;
122 	float turn;
123 
124 	int shield_damage;
125 
126 	struct bullet *next;
127 
128 	int dying;
129 	int delete_me;
130 };
131 
132 struct diamond {
133 	int x, y;
134 	int room;
135 	int t;
136 	struct diamond *next;
137 	struct diamond *next_in_room;
138 	struct diamond *prv_in_room;
139 	int value;
140 	int delete_me;
141 };
142 
143 struct enemyloc {
144 	struct enemy *e;
145 	struct enemyloc *n;
146 };
147 
148 int total_enemies = 0;
149 int killed_enemies = 0;
150 int total_bullets = 0;
151 int active_enemies = 0;
152 int total_gems = 0;
153 
154 struct enemy *enemy_stack = NULL;
155 struct bullet *bullet_stack = NULL;
156 struct enemy *active_stack = NULL;
157 struct diamond *gem_stack = NULL;
158 
159 struct diamond *room_gems[3000] = {NULL};
160 
161 struct enemyloc *enemy_loc_stack[20][20] = {{NULL}};
162 
163 struct enemy *CreateEnemy(int enemy_x, int enemy_y, int enemy_room);
164 struct enemy *CreateEnemyEx(int enemy_x, int enemy_y, int enemy_room, int enemy_type);
165 void SCreateGem(int x, int y, int r, int v);
166 void ActivateEnemies(int room);
167 void SoupUpEnemies();
168 
169 void SpawnLaser(int x, int y, float dir, int fire_time, int duration, float turn, int dmg);
170 
DestroyThings()171 void DestroyThings()
172 {
173 	struct enemy *ec, *ed;
174 	struct bullet *bc, *bd;
175 	struct diamond *dc, *dd;
176 	int i;
177 
178 	ec = enemy_stack;
179 	bc = bullet_stack;
180 	dc = gem_stack;
181 
182 	while (ec) {
183 		ed = ec;
184 		ec = ec->next;
185 		free(ed);
186 	}
187 	while (bc) {
188 		bd = bc;
189 		bc = bc->next;
190 		free(bd);
191 	}
192 	while (dc) {
193 		dd = dc;
194 		dc = dc->next;
195 		free(dd);
196 	}
197 
198 	enemy_stack = NULL;
199 	bullet_stack = NULL;
200 	gem_stack = NULL;
201 	active_stack = NULL;
202 
203 	for (i = 0; i < 3000; i++) {
204 		room_gems[i] = NULL;
205 	}
206 }
207 
208 struct GRD_Box {
209 	int d[60][60];
210 };
211 int GetRoomDist(int room1, int room2);
FindRoomDist(int room1,int room2)212 int FindRoomDist(int room1, int room2)
213 {
214 	struct RoomConnection *follow;
215 	int mdist = 1000000;
216 	int cdist;
217 
218 	if (room1 == room2) return 0;
219 	fc_open++;
220 
221 	searched[room1] = csearch;
222 
223 	follow = rooms[room1].con;
224 	while (follow != NULL) {
225 		if (searched[follow->c] != csearch) {
226 			cdist = GetRoomDist(follow->c, room2);
227 
228 			if (cdist < mdist) {
229 				mdist = cdist;
230 			}
231 		}
232 		follow = follow->n;
233 	}
234 	fc_open--;
235 	return mdist;
236 }
237 
GetRoomDist(int room1,int room2)238 int GetRoomDist(int room1, int room2)
239 {
240 	int gx, gy, dx, dy;
241 	int temp;
242 	int ix, iy;
243 	static struct GRD_Box *g[50][50] = {{NULL}};
244 
245 	fc_open++;
246 
247 	if (room2 < room1) {
248 		temp = room2;
249 		room2 = room1;
250 		room1 = temp;
251 	}
252 
253 	gx = room1 / 60;
254 	dx = room1 % 60;
255 	gy = room2 / 60;
256 	dy = room2 % 60;
257 
258 	if (g[gx][gy] == NULL) {
259 		g[gx][gy] = malloc(sizeof(struct GRD_Box));
260 		for (iy = 0; iy < 60; iy++) {
261 			for (ix = 0; ix < 60; ix++) {
262 				g[gx][gy]->d[ix][iy] = -1;
263 			}
264 		}
265 	}
266 
267 	if (g[gx][gy]->d[dx][dy] == -1) {
268 		g[gx][gy]->d[dx][dy] = FindRoomDist(room1, room2);
269 	}
270 	fc_open--;
271 	return g[gx][gy]->d[dx][dy];
272 }
273 
AddEnemyLoc(struct enemy * e,int x,int y)274 void AddEnemyLoc(struct enemy *e, int x, int y)
275 {
276 	struct enemyloc *next;
277 	x+=1;
278 	y+=1;
279 	next = enemy_loc_stack[x][y];
280 	enemy_loc_stack[x][y] = malloc(sizeof(struct enemyloc));
281 	enemy_loc_stack[x][y]->n = next;
282 	enemy_loc_stack[x][y]->e = e;
283 }
284 
GetEnemyLoc(int s_x,int s_y)285 struct enemyloc *GetEnemyLoc(int s_x, int s_y)
286 {
287 	return enemy_loc_stack[s_x / 1100 + 1][s_y / 1100 + 1];
288 }
289 
AddEnemyPos(struct enemy * e)290 void AddEnemyPos(struct enemy *e)
291 {
292 	int x_loc, y_loc, ix, iy;
293 	x_loc = (e->x) / 1100;
294 	y_loc = (e->y) / 1100;
295 	AddEnemyLoc(e, x_loc, y_loc);
296 	ix = ((e->x - screen->w) / 1100);
297 	iy = ((e->y - screen->h) / 1100);
298 	if (x_loc != ix) {
299 		AddEnemyLoc(e, ix, y_loc);
300 	}
301 	if (y_loc != iy) {
302 		AddEnemyLoc(e, x_loc, iy);
303 	}
304 	if ((x_loc != ix) && (y_loc != iy)) {
305 		AddEnemyLoc(e, ix, iy);
306 	}
307 }
308 
WriteEnemyData()309 void WriteEnemyData()
310 {
311 	struct enemy *ptr;
312 	int n = 0;
313 	int i = 0;
314 
315 	ptr = enemy_stack;
316 	while (ptr != NULL) {
317 		if (!ptr->delete_me) n++;
318 		ptr = ptr->next;
319 	}
320 	FWInt(n);
321 	ptr = enemy_stack;
322 	while (ptr != NULL) {
323 		if (!ptr->delete_me) {
324 			FWInt(ptr->x);
325 			FWInt(ptr->y);
326 			FWInt(ptr->room);
327 			FWInt(ptr->enemy_type);
328 			i++;
329 			if (i % 100 == 99) {
330 				SavingScreen(2, (float)i / (float)n);
331 			}
332 		}
333 		ptr = ptr->next;
334 	}
335 }
336 
WriteGemData()337 void WriteGemData()
338 {
339 	struct diamond *ptr;
340 	int n = 0;
341 	int i = 0;
342 
343 	ptr = gem_stack;
344 	while (ptr != NULL) {
345 		if (!ptr->delete_me) n++;
346 		ptr = ptr->next;
347 	}
348 	FWInt(n);
349 	ptr = gem_stack;
350 	while (ptr != NULL) {
351 		if (!ptr->delete_me) {
352 			FWInt(ptr->x);
353 			FWInt(ptr->y);
354 			FWInt(ptr->room);
355 			FWInt(ptr->value);
356 
357 			i++;
358 			if (i % 100 == 99) {
359 				SavingScreen(3, (float)i / (float)n);
360 			}
361 		}
362 		ptr = ptr->next;
363 	}
364 }
365 
WriteCreatureData()366 void WriteCreatureData()
367 {
368 	FWInt(total_enemies);
369 	FWInt(killed_enemies);
370 
371 	WriteEnemyData();
372 	WriteGemData();
373 }
374 
ReadEnemyData()375 void ReadEnemyData()
376 {
377 	int i, n;
378 	int x, y, room, t;
379 
380 	n = FRInt();
381 
382 	for (i = 0; i < n; i++) {
383 		x = FRInt();
384 		y = FRInt();
385 		room = FRInt();
386 		t = FRInt();
387 		CreateEnemyEx(x, y, room, t);
388 		total_enemies--;
389 
390 		if (i % 100 == 99) {
391 			LoadingScreen(2, (float)i / (float)n);
392 		}
393 	}
394 	LoadingScreen(2, 1);
395 }
396 
ReadGemData()397 void ReadGemData()
398 {
399 	int i, n;
400 	int x, y, room, value;
401 
402 	n = FRInt();
403 
404 	for (i = 0; i < n; i++) {
405 		x = FRInt();
406 		y = FRInt();
407 		room = FRInt();
408 		value = FRInt();
409 		SCreateGem(x, y, room, value);
410 
411 		if (i % 100 == 99) {
412 			LoadingScreen(3, (float)i / (float)n);
413 		}
414 	}
415 	LoadingScreen(3, 1);
416 }
417 
ActivateVisited()418 void ActivateVisited()
419 {
420 	int i;
421 
422 
423 	for (i = 0; i < 3000; i++) {
424 		if (rooms[i].visited) {
425 			ActivateEnemies(i);
426 		}
427 		if (i % 10 == 9) {
428 			LoadingScreen(4, (float)i / 3000.0);
429 		}
430 	}
431 	LoadingScreen(4, 1);
432 }
433 
ReadCreatureData()434 void ReadCreatureData()
435 {
436 	total_enemies = FRInt();
437 	killed_enemies = FRInt();
438 
439 	ReadEnemyData();
440 	ReadGemData();
441 	ActivateVisited();
442 }
443 
444 SDL_Surface *enemy_sprites[10];
445 
AllocateEnemy()446 struct enemy * AllocateEnemy()
447 {
448 	return malloc(sizeof(struct enemy));
449 }
450 
AllocateBullet()451 struct bullet * AllocateBullet()
452 {
453 	return malloc(sizeof(struct bullet));
454 }
455 
AllocateGem()456 struct diamond * AllocateGem()
457 {
458 	return malloc(sizeof(struct diamond));
459 }
460 
CreateEnemy(int enemy_x,int enemy_y,int enemy_room)461 struct enemy *CreateEnemy(int enemy_x, int enemy_y, int enemy_room)
462 {
463 	int enemy_type;
464 
465 	enemy_type = rand() % (rooms[enemy_room].s_dist / 5 + 1);
466 	if (rooms[enemy_room].room_type == 5) enemy_type += rand()%3;
467 	if (enemy_type > 8) enemy_type = rand()%3+6;
468 
469 	if (rooms[enemy_room].s_dist >= 15) {
470 		if (rand()%64 == 0) {
471 			enemy_type = 9;
472 		}
473 	}
474 
475 
476 	return CreateEnemyEx(enemy_x, enemy_y, enemy_room, enemy_type);
477 }
478 
CreateEnemyEx(int enemy_x,int enemy_y,int enemy_room,int enemy_type)479 struct enemy *CreateEnemyEx(int enemy_x, int enemy_y, int enemy_room, int enemy_type)
480 {
481 	struct enemy *new_enemy;
482 
483 	new_enemy = AllocateEnemy();
484 	new_enemy->x = enemy_x;
485 	new_enemy->y = enemy_y;
486 	new_enemy->room = enemy_room;
487 
488 	rooms[enemy_room].enemies++;
489 	new_enemy->deaths = 0;
490 	new_enemy->t = rand() % 65536;
491 	new_enemy->active = 0;
492 	new_enemy->curr_follow = -1;
493 	new_enemy->teleport_v = 0;
494 
495 	new_enemy->m_exit = NULL;
496 
497 	new_enemy->dying = 0;
498 	new_enemy->delete_me = 0;
499 
500 	new_enemy->last_room = -1;
501 	new_enemy->p_last_room = -1;
502 
503 	new_enemy->enemy_type = enemy_type;
504 
505 	new_enemy->followdepth = 4;
506 
507 	switch (enemy_type) {
508 		case 0:
509 			new_enemy->image = enemy_sprites[0];
510 			new_enemy->lives = 1;
511 			new_enemy->str = 20;
512 			new_enemy->speed = 3;
513 			new_enemy->fire_rate = 20;
514 			new_enemy->min_gems = 0;
515 			new_enemy->max_gems = 3;
516 			new_enemy->creationcost = 1;
517 			break;
518 		case 1:
519 			new_enemy->image = enemy_sprites[1];
520 			new_enemy->lives = 1;
521 			new_enemy->str = 50;
522 			new_enemy->speed = 4;
523 			new_enemy->fire_rate = 25;
524 			new_enemy->min_gems = 2;
525 			new_enemy->max_gems = 6;
526 			new_enemy->creationcost = 1;
527 			break;
528 		case 2:
529 			new_enemy->image = enemy_sprites[2];
530 			new_enemy->lives = 1;
531 			new_enemy->str = 180;
532 			new_enemy->speed = 5;
533 			new_enemy->fire_rate = 40;
534 			new_enemy->min_gems = 8;
535 			new_enemy->max_gems = 15;
536 			new_enemy->creationcost = 1;
537 			break;
538 		case 3:
539 			new_enemy->image = enemy_sprites[3];
540 			new_enemy->lives = 2;
541 			new_enemy->str = 220;
542 			new_enemy->speed = 3;
543 			new_enemy->fire_rate = 24;
544 			new_enemy->min_gems = 12;
545 			new_enemy->max_gems = 20;
546 			new_enemy->creationcost = 1;
547 			break;
548 		case 4:
549 			new_enemy->image = enemy_sprites[4];
550 			new_enemy->lives = 1;
551 			new_enemy->str = 360;
552 			new_enemy->speed = 3;
553 			new_enemy->fire_rate = 32;
554 			new_enemy->min_gems = 18;
555 			new_enemy->max_gems = 32;
556 			new_enemy->creationcost = 2;
557 			break;
558 		case 5:
559 			new_enemy->image = enemy_sprites[5];
560 			new_enemy->lives = 1;
561 			new_enemy->str = 450;
562 			new_enemy->speed = 3;
563 			new_enemy->fire_rate = 2;
564 			new_enemy->min_gems = 32;
565 			new_enemy->max_gems = 64;
566 			new_enemy->creationcost = 2;
567 			break;
568 		case 6:
569 			new_enemy->image = enemy_sprites[6];
570 			new_enemy->lives = 2;
571 			new_enemy->str = 450;
572 			new_enemy->speed = 4;
573 			new_enemy->fire_rate = 10;
574 			new_enemy->min_gems = 50;
575 			new_enemy->max_gems = 100;
576 			new_enemy->creationcost = 2;
577 			break;
578 		case 7:
579 			new_enemy->image = enemy_sprites[7];
580 			new_enemy->lives = 1;
581 			new_enemy->str = 500;
582 			new_enemy->speed = 4;
583 			new_enemy->fire_rate = 27;
584 			new_enemy->min_gems = 80;
585 			new_enemy->max_gems = 160;
586 			new_enemy->creationcost = 3;
587 			break;
588 		case 8:
589 			new_enemy->image = enemy_sprites[8];
590 			new_enemy->lives = 4;
591 			new_enemy->str = 500;
592 			new_enemy->speed = 2;
593 			new_enemy->fire_rate = 8;
594 			new_enemy->min_gems = 200;
595 			new_enemy->max_gems = 400;
596 			new_enemy->creationcost = 4;
597 			break;
598 		case 9:
599 			new_enemy->image = enemy_sprites[0];
600 			new_enemy->lives = 1;
601 			new_enemy->str = rooms[enemy_room].s_dist * 20;
602 			new_enemy->speed = 3;
603 			new_enemy->fire_rate = 21;
604 			new_enemy->min_gems = 300;
605 			new_enemy->max_gems = 600;
606 			new_enemy->creationcost = 3;
607 			break;
608 		case 10:
609 			new_enemy->image = enemy_sprites[9];
610 			new_enemy->lives = 8;
611 			new_enemy->str = 500;
612 			new_enemy->speed = 1;
613 			new_enemy->fire_rate = 4;
614 			new_enemy->min_gems = 5000;
615 			new_enemy->max_gems = 6000;
616 			new_enemy->followdepth = 8;
617 			new_enemy->creationcost = 6;
618 			break;
619 	}
620 
621 	if (training) {
622 		new_enemy->str = new_enemy->str * 4 / 5;
623 		new_enemy->fire_rate += (new_enemy->fire_rate / 2);
624 		new_enemy->speed *= 2;
625 	}
626 
627 	if (rooms[new_enemy->room].room_type == 5) {
628 		new_enemy->str = new_enemy->str * 3 / 2;
629 		if (new_enemy->str > 1500) new_enemy->str = 1500;
630 		new_enemy->fire_rate = new_enemy->fire_rate - 1;
631 	}
632 
633 	new_enemy->blit_pos = (rand()%(new_enemy->image->w / (new_enemy->image->h/new_enemy->lives)))*(new_enemy->image->h/new_enemy->lives);
634 	new_enemy->next_active = NULL;
635 
636 	new_enemy->next = enemy_stack;
637 	enemy_stack = new_enemy;
638 
639 	AddEnemyPos(new_enemy);
640 
641 	total_enemies++;
642 
643 	return new_enemy;
644 }
645 
SCreateGem(int x,int y,int r,int v)646 void SCreateGem(int x, int y, int r, int v)
647 {
648 	struct diamond *new_gem;
649 
650 	if (TileData[Get(x / 32, y / 32)].Is_Solid) {
651 		return;
652 	}
653 	if (GetRoom(x / 32, y / 32) != r) {
654 		return;
655 	}
656 	if (v == 0) {
657 		return;
658 	}
659 
660 	new_gem = AllocateGem();
661 
662 	new_gem->x = x;
663 	new_gem->y = y;
664 	new_gem->room = r;
665 new_gem->delete_me = 0;
666 	new_gem->t = rand()%65536;
667 	new_gem->next = gem_stack;
668 	new_gem->next_in_room = room_gems[r];
669 
670 	if (room_gems[r] != NULL) {
671 		room_gems[r]->prv_in_room = new_gem;
672 	}
673 
674 	new_gem->value = v;
675 	new_gem->prv_in_room = NULL;
676 	gem_stack = new_gem;
677 	room_gems[r] = new_gem;
678 
679 	total_gems++;
680 }
681 
CreateGem(int x,int y,int r,int v)682 void CreateGem(int x, int y, int r, int v)
683 {
684 	if (v == 0) return;
685 	if ( (rand()%1000) < ((int)log(v)/4 + (player_hp == 1)*5 + 2) ) {
686 		SCreateGem(x, y, r, 31337);
687 	} else {
688 		SCreateGem(x, y, r, v);
689 	}
690 }
691 
PlayerDir(int x,int y)692 float PlayerDir(int x, int y)
693 {
694 	float dy = player_y+12 - y;
695 	float dx = player_x+8 - x;
696 	return atan2(dy, dx);
697 }
698 
PlayerDist(int x,int y)699 int PlayerDist(int x, int y)
700 {
701 	int d = sqrt(sqr(x-(player_x+8))+sqr(y-(player_y+12)));
702 	return d;
703 }
704 
CreateBullet(int x,int y,struct enemy * firer,int bullet_type,float dir,float spd)705 struct bullet *CreateBullet(int x, int y, struct enemy *firer, int bullet_type, float dir, float spd)
706 {
707 	struct bullet *new_shot;
708 
709 	new_shot = AllocateBullet();
710 	new_shot->x = x;
711 	new_shot->y = y;
712 	new_shot->firer = firer;
713 	if (firer != NULL) {
714 		new_shot->room = firer->room;
715 	} else {
716 		new_shot->room = GetRoom(x / 32, y / 32);
717 	}
718 	new_shot->dying = 0;
719 	new_shot->delete_me = 0;
720 	new_shot->t = rand() % 65536;
721 	new_shot->dir = dir;
722 	new_shot->speed = spd;
723 	new_shot->invuln = 0;
724 	new_shot->parent = NULL;
725 
726 	switch (bullet_type) {
727 		case 0:
728 			new_shot->img = 0;
729 			break;
730 		case 1:
731 			new_shot->img = 1;
732 			new_shot->invuln = 1;
733 			break;
734 		case 2:
735 			new_shot->img = 2;
736 			new_shot->invuln = 1;
737 			new_shot->t = 0;
738 			new_shot->fire_time = 30;
739 			new_shot->duration = 30;
740 			new_shot->turn = 0.0;
741 			new_shot->speed = 0.0;
742 			break;
743 		case 3:
744 			new_shot->img = 3;
745 			break;
746 		case 4:
747 			new_shot->img = 4;
748 			new_shot->invuln = 1;
749 			break;
750 		case 5:
751 			new_shot->img = 5;
752 			new_shot->t = 0;
753 			break;
754 		case 6:
755 			new_shot->img = 6;
756 			new_shot->invuln = 1;
757 			break;
758 		case 7:
759 			new_shot->img = 7;
760 			new_shot->invuln = 1;
761 			break;
762 		case 8:
763 			new_shot->img = 8;
764 			new_shot->invuln = 1;
765 			break;
766 	}
767 	if (training) {
768 		new_shot->speed *= 0.8;
769 	}
770 	new_shot->next = bullet_stack;
771 	bullet_stack = new_shot;
772 
773 	total_bullets++;
774 	return new_shot;
775 }
776 
FireLaser(int x,int y,struct enemy * firer,float dir,int fire_time,int duration,float turn,int dmg)777 struct bullet *FireLaser(int x, int y, struct enemy *firer, float dir, int fire_time, int duration, float turn, int dmg)
778 {
779 	int f_total;
780 	struct bullet *b;
781 	b = CreateBullet(x, y, firer, 2, dir, 0);
782 	b->fire_time = fire_time;
783 	b->duration = duration;
784 	b->turn = turn;
785 	b->shield_damage = dmg;
786 
787 	if (training) {
788 		f_total = b->fire_time + b->duration;
789 		if (b->duration > 1) {
790 			b->duration /= 2;
791 			b->fire_time = f_total - b->duration;
792 		}
793 		b->shield_damage = (b->shield_damage + 1) / 2;
794 	}
795 	return b;
796 }
797 
InitEnemySprites()798 void InitEnemySprites()
799 {
800 	enemy_sprites[0] = IMG_Load("/usr/local/share/meritous/i/mons1.png");
801 	SDL_SetColorKey(enemy_sprites[0], SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
802 	enemy_sprites[1] = IMG_Load("/usr/local/share/meritous/i/mons2.png");
803 	SDL_SetColorKey(enemy_sprites[1], SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
804 	enemy_sprites[2] = IMG_Load("/usr/local/share/meritous/i/mons3.png");
805 	SDL_SetColorKey(enemy_sprites[2], SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
806 	enemy_sprites[3] = IMG_Load("/usr/local/share/meritous/i/mons4.png");
807 	SDL_SetColorKey(enemy_sprites[3], SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
808 	enemy_sprites[4] = IMG_Load("/usr/local/share/meritous/i/mons5.png");
809 	SDL_SetColorKey(enemy_sprites[4], SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
810 	enemy_sprites[5] = IMG_Load("/usr/local/share/meritous/i/mons6.png");
811 	SDL_SetColorKey(enemy_sprites[5], SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
812 	enemy_sprites[6] = IMG_Load("/usr/local/share/meritous/i/mons7.png");
813 	SDL_SetColorKey(enemy_sprites[6], SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
814 	enemy_sprites[7] = IMG_Load("/usr/local/share/meritous/i/mons8.png");
815 	SDL_SetColorKey(enemy_sprites[7], SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
816 	enemy_sprites[8] = IMG_Load("/usr/local/share/meritous/i/mons9.png");
817 	SDL_SetColorKey(enemy_sprites[8], SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
818 	enemy_sprites[9] = IMG_Load("/usr/local/share/meritous/i/mons10.png");
819 	SDL_SetColorKey(enemy_sprites[9], SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
820 
821 	reticle = IMG_Load("/usr/local/share/meritous/i/reticle.png");
822 	SDL_SetColorKey(reticle, SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
823 
824 	inrange = IMG_Load("/usr/local/share/meritous/i/inrange.png");
825 	SDL_SetColorKey(inrange, SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
826 
827 	invis_enemy = IMG_Load("/usr/local/share/meritous/i/hidden_monster.png");
828 	SDL_SetColorKey(invis_enemy, SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
829 }
830 
ActivateSingleEnemy(struct enemy * t)831 void ActivateSingleEnemy(struct enemy *t)
832 {
833 	struct enemy *new_active;
834 
835 	if (t->active) return;
836 
837 	if (t->enemy_type != 10) {
838 		if (t->enemy_type == 9) {
839 			if (max_activate_dist < 10) return;
840 		} else {
841 
842 			if (t->enemy_type > (max_activate_dist / 5 + 2)) return;
843 
844 		}
845 	}
846 
847 	new_active = t;
848 	new_active->next_active = active_stack;
849 	active_stack = new_active;
850 
851 	active_enemies += 1;
852 	t->active = 1;
853 }
854 
XActivateSingleEnemy(struct enemy * t)855 void XActivateSingleEnemy(struct enemy *t)
856 {
857 	if (rooms[t->room].room_type == 2) return;
858 	if (rooms[t->room].room_type == 3) return;
859 
860 	ActivateSingleEnemy(t);
861 }
862 
InitEnemies()863 void InitEnemies()
864 {
865 	int c_room;
866 	int cr_w, cr_h, cr_x, cr_y;
867 	int room_size;
868 	int n_enemies;
869 	int i;
870 	int trying;
871 	int e_x, e_y;
872 	int nx, ny;
873 
874 	max_activate_dist = 0;
875 
876 	InitEnemySprites();
877 
878 	for (ny = 0; ny < 20; ny++) {
879 		for (nx = 0; nx < 20; nx++) {
880 			enemy_loc_stack[nx][ny] = NULL;
881 		}
882 	}
883 
884 	total_enemies = 0;
885 	killed_enemies = 0;
886 	total_bullets = 0;
887 	active_enemies = 0;
888 	total_gems = 0;
889 
890 	for (i = 0; i < 3000; i++) {
891 		room_active[i] = 0;
892 	}
893 
894 	if (game_load) {
895 		ReadCreatureData();
896 		if (current_boss > 0) SoupUpEnemies();
897 	} else {
898 		for (c_room = 1; c_room < 3000; c_room++) {
899 			cr_x = rooms[c_room].x + 1;
900 			cr_y = rooms[c_room].y + 1;
901 			cr_w = rooms[c_room].w - 2;
902 			cr_h = rooms[c_room].h - 2;
903 			room_size = cr_w * cr_h;
904 
905 			n_enemies = rand() % ((room_size / 4) + 1);
906 
907 			if (rooms[c_room].room_type == 2) {
908 				n_enemies = 0;
909 			}
910 
911 			if (rooms[c_room].room_type == 3) {
912 				n_enemies += (n_enemies + room_size) / 2;
913 			}
914 
915 			if (rooms[c_room].room_type == 5) {
916 				n_enemies = 50;
917 			}
918 
919 			while (n_enemies > 0) {
920 				trying = 1;
921 				while (trying) {
922 					e_x = cr_x * 32 + 32 + rand() % (cr_w * 32 - 64 + 1);
923 					e_y = cr_y * 32 + 32 + rand() % (cr_h * 32 - 64 + 1);
924 
925 					if ((!IsSolid(Get( (e_x-16) /32, (e_y-16) /32)))&&(!IsSolid(Get( (e_x+16) /32, (e_y-16) /32)))) {
926 						if ((!IsSolid(Get( (e_x-16) /32, (e_y+16) /32)))&&(!IsSolid(Get( (e_x+16) /32, (e_y+16) /32)))) {
927 							n_enemies -= (CreateEnemy(e_x, e_y, c_room))->creationcost;
928 							trying = 0;
929 						}
930 					}
931 				}
932 			}
933 			if (c_room % 100 == 99) {
934 				LoadingScreen(2, (float)c_room / 3000.0);
935 			}
936 		}
937 	}
938 
939 
940 }
941 
EnemyMovement(struct enemy * e,int move_x,int move_y)942 int EnemyMovement(struct enemy *e, int move_x, int move_y)
943 {
944 	if (!IsSolid(Get( (move_x - 12)/32, (move_y - 12)/32))) {
945 		if (!IsSolid(Get( (move_x + 12)/32, (move_y - 12)/32))) {
946 			if (!IsSolid(Get( (move_x - 12)/32, (move_y + 12)/32))) {
947 				if (!IsSolid(Get( (move_x + 12)/32, (move_y + 12)/32))) {
948 					e->x = move_x;
949 					e->y = move_y;
950 					return 1;
951 				}
952 			}
953 		}
954 	}
955 	return 0;
956 }
957 
958 // Only activate SOME enemies. A room can only be ZActivated once
ZActivateEnemies(int room)959 void ZActivateEnemies(int room)
960 {
961 	struct enemy *t;
962 	struct RoomConnection *rc;
963 
964 	if (room_active[room]) return;
965 	room_active[room] = 1;
966 
967 	t = enemy_stack;
968 
969 	while (t != NULL) {
970 		// 1/4 chance of activating each enemy
971 		if (rand()%4 == 0) {
972 			if (t->room == room) {
973 				if (t->active == 0) {
974 					XActivateSingleEnemy(t);
975 				}
976 			}
977 		}
978 		t = t->next;
979 	}
980 
981 	// 1/3 chance of activating each adjacent room
982 	rc = rooms[room].con;
983 	while (rc != NULL) {
984 		if (rand()%3 == 0) {
985 			ZActivateEnemies(rc->c);
986 		}
987 		rc = rc->n;
988 	}
989 }
990 
ActivateEnemies(int room)991 void ActivateEnemies(int room)
992 {
993 	struct enemy *t;
994 	struct RoomConnection *rc;
995 
996 	t = enemy_stack;
997 
998 	if (rooms[room].s_dist > max_activate_dist) {
999 		max_activate_dist = rooms[room].s_dist;
1000 	}
1001 
1002 	while (t != NULL) {
1003 		if (t->room == room) {
1004 			if (t->active == 0) {
1005 				ActivateSingleEnemy(t);
1006 
1007 				if (rooms[room].room_type == 3) {
1008 					t->teleport_v = (rand() % 1500) + 50;
1009 				}
1010 			}
1011 		}
1012 		t = t->next;
1013 	}
1014 
1015 	// 1/2 chance of activating each adjacent room
1016 	rc = rooms[room].con;
1017 	while (rc != NULL) {
1018 		if (rand()%2 == 0) {
1019 			if ((rooms[rc->c].room_type != 2) && (rooms[rc->c].room_type != 3))  {
1020 				ZActivateEnemies(rc->c);
1021 			}
1022 		}
1023 		rc = rc->n;
1024 	}
1025 }
1026 
CanEnterRoom(int room)1027 int CanEnterRoom(int room)
1028 {
1029 	if (room == 0) return 0;
1030 	if (rooms[room].room_type == 2) return 0;
1031 	if (rooms[room].room_type == 3) return 0;
1032 	if (rooms[room].room_type == 5) return 0;
1033 	if (rooms[room].room_type == 6) return 0;
1034 
1035 	if (artifacts[11]) {
1036 		if (rooms[room].enemies > 3) {
1037 			return 0;
1038 		}
1039 	}
1040 
1041 	return 1;
1042 }
CanLeaveRoom(int room)1043 int CanLeaveRoom(int room)
1044 {
1045 	if (room == 0) return 0;
1046 	if (rooms[room].room_type == 2) return 0;
1047 	if (rooms[room].room_type == 3) return 0;
1048 	if (rooms[room].room_type == 5) return 0;
1049 	if (rooms[room].room_type == 6) return 0;
1050 
1051 	return 1;
1052 }
1053 
RecurseFind(struct enemy * e,int room,int depth)1054 int RecurseFind(struct enemy *e, int room, int depth)
1055 {
1056 	struct RoomConnection *follow;
1057 	int dpth;
1058 	int mindpth = 1000000;
1059 	follow = rooms[room].con;
1060 
1061 	if (CanEnterRoom(room) == 0) return 0;
1062 
1063 	if (room == player_room) return depth+1;
1064 	if (searched[room] == csearch) {
1065 		if (searchdist[room] < depth)
1066 			return 0;
1067 	}
1068 	if (depth > e->followdepth) return 0;
1069 	if ((e->last_room == room) && (e->p_last_room == player_room)) return 0;
1070 
1071 	searched[room] = csearch;
1072 	searchdist[room] = depth;
1073 
1074 	while (follow != NULL) {
1075 		if ((dpth = RecurseFind(e, follow->c, depth+1)) > 0) {
1076 			if (dpth < mindpth) {
1077 				mindpth = dpth;
1078 			}
1079 		}
1080 		follow = follow->n;
1081 	}
1082 
1083 	if (mindpth != 1000000) {
1084 		return mindpth;
1085 	}
1086 
1087 	return 0;
1088 
1089 }
1090 
FollowPlayer(struct enemy * e,struct RoomConnection ** rcon)1091 int FollowPlayer(struct enemy *e, struct RoomConnection **rcon)
1092 {
1093 	struct RoomConnection *follow;
1094 	int mindepth = 1000000;
1095 	int newdepth;
1096 	int mdist = 1000000;
1097 	int ndist = 0;
1098 	int rdepth[4000];
1099 
1100 	return 0;
1101 	follow = rooms[e->room].con;
1102 
1103 	while (follow != NULL) {
1104 		if (follow->c == player_room) {
1105 			if (CanEnterRoom(follow->c)) {
1106 				*rcon = follow;
1107 				e->curr_follow = (*rcon)->c;
1108 				return 1;
1109 			}
1110 		}
1111 		follow = follow->n;
1112 	}
1113 
1114 	// Recursively follow the player, to a certain depth
1115 	follow = rooms[e->room].con;
1116 	csearch = rand();
1117 
1118 	// Are we already following the player into a room?
1119 
1120 	/*if (e->curr_follow != -1) {
1121 		// See if this room is the best FIRST
1122 		newdepth = RecurseFind(e, e->curr_follow, 0);
1123 		if (newdepth > 0) {
1124 			mindepth = newdepth;
1125 			*rcon = follow;
1126 		}
1127 	}*/
1128 
1129 	while (follow != NULL) {
1130 		if (CanEnterRoom(follow->c)) {
1131 			newdepth = RecurseFind(e, follow->c, 0);
1132 			rdepth[follow->c] = newdepth;
1133 			if (newdepth > 0) {
1134 				if (mindepth > newdepth) {
1135 					mindepth = newdepth;
1136 					*rcon = follow;
1137 				}
1138 			}
1139 		}
1140 		follow = follow->n;
1141 	}
1142 	if (mindepth != 1000000) {
1143 		follow = rooms[e->room].con;
1144 		while (follow != NULL) {
1145 			if (CanEnterRoom(follow->c)) {
1146 				newdepth = rdepth[follow->c];
1147 				if (newdepth == mindepth) {
1148 					ndist = PlayerDist(follow->x*32+16, follow->y*32+16);
1149 					if (ndist < mdist) {
1150 						mdist = ndist;
1151 						*rcon = follow;
1152 					}
1153 				}
1154 			}
1155 			follow = follow->n;
1156 		}
1157 
1158 		e->curr_follow = (*rcon)->c;
1159 		return mindepth;
1160 	}
1161 	return 0;
1162 }
1163 
KillEnemy(struct enemy * t)1164 void KillEnemy(struct enemy *t)
1165 {
1166 	static int lastkill = 0;
1167 	int ct;
1168 
1169 	if (t->dying > 0) return;
1170 	if (t->teleport_v > 0) return;
1171 	if (t->delete_me) return;
1172 
1173 	ct = SDL_GetTicks();
1174 
1175 	if ((ct - lastkill) > 100) {
1176 		SND_Pos("/usr/local/share/meritous/a/enemyhit.wav", 128, PlayerDist(t->x, t->y));
1177 		lastkill = ct;
1178 	}
1179 
1180 	t->dying = 1;
1181 }
1182 
ArtifactRoomUnlock(int room)1183 void ArtifactRoomUnlock(int room)
1184 {
1185 	struct enemy *e;
1186 	int x, y, rx, ry, rt;
1187 	int placed;
1188 	int tot_treasures;
1189 
1190 	e = active_stack;
1191 	while (e != NULL) {
1192 		if ((e->delete_me == 0) && (e->room == room)) {
1193 			return;
1194 		}
1195 		e = e->next_active;
1196 	}
1197 
1198 	// unlock doors
1199 
1200 	for (y = 0; y < rooms[room].h; y++) {
1201 		for (x = 0; x < rooms[room].w; x++) {
1202 			rx = x + rooms[room].x;
1203 			ry = y + rooms[room].y;
1204 			rt = Get(rx, ry);
1205 
1206 			if ((rt >= 21) && (rt <= 24)) {
1207 				Put(rx, ry, rt - 21 + 13, room);
1208 			}
1209 		}
1210 	}
1211 
1212 	// place treasure
1213 	placed = 0;
1214 	tot_treasures = 2 + rand() % (rooms[room].s_dist / 8 + 1);
1215 	while (placed < tot_treasures) {
1216 		x = rooms[room].x + (rand() % (rooms[room].w - 2));
1217 		y = rooms[room].y + (rand() % (rooms[room].h - 2));
1218 		//printf("Attempting %d, %d\n", x, y);
1219 		if ((x+y)%2 == (placed>0)) {
1220 			//printf("Correct placement type\n");
1221 			if (!IsSolid(Get(x, y))) {
1222 				//printf("Not solid\n");
1223 				Put(x, y, 26, room);
1224 				placed++;
1225 			}
1226 		}
1227 		fflush(stdout);
1228 	}
1229 
1230 	// sign room
1231 	rooms[room].room_type = 4;
1232 }
1233 
EnemySound(int t,int dist)1234 void EnemySound(int t, int dist)
1235 {
1236 	static int last_e_sound = 0;
1237 	static int last_delay = 150;
1238 	int curr_e_sound = SDL_GetTicks();
1239 
1240 	if ((curr_e_sound - last_delay) < last_e_sound) {
1241 		return;
1242 	}
1243 
1244 	switch (t) {
1245 		case 0:
1246 			SND_Pos("/usr/local/share/meritous/a/mons0shot.wav", 48, dist);
1247 			last_delay = 200;
1248 		break;
1249 		case 1:
1250 			SND_Pos("/usr/local/share/meritous/a/mons1shot.wav", 112, dist);
1251 			last_delay = 500;
1252 		break;
1253 		case 2:
1254 			SND_Pos("/usr/local/share/meritous/a/mons2shot.wav", 110, dist);
1255 			last_delay = 1000;
1256 		break;
1257 		case 3:
1258 			SND_Pos("/usr/local/share/meritous/a/mons3shot.wav", 110, dist);
1259 			last_delay = 500;
1260 		break;
1261 		case 4:
1262 			SND_Pos("/usr/local/share/meritous/a/mons4shot.wav", 110, dist);
1263 			last_delay = 900;
1264 		break;
1265 		case 5:
1266 			SND_Pos("/usr/local/share/meritous/a/mons5shot.wav", 80, dist);
1267 			last_delay = 60;
1268 		break;
1269 		case 6:
1270 			SND_Pos("/usr/local/share/meritous/a/mons6shot.wav", 110, dist);
1271 			last_delay = 1000;
1272 		break;
1273 		case 7:
1274 			SND_Pos("/usr/local/share/meritous/a/mons7shot.wav", 110, dist);
1275 			last_delay = 600;
1276 		break;
1277 		case 8:
1278 			SND_Pos("/usr/local/share/meritous/a/mons8shot.wav", 110, dist);
1279 			last_delay = 700;
1280 		break;
1281 		case 9:
1282 			SND_Pos("/usr/local/share/meritous/a/mons9shot.wav", 110, dist);
1283 			last_delay = 242;
1284 		break;
1285 		case 10:
1286 			SND_Pos("/usr/local/share/meritous/a/mons10shot.wav", 110, dist);
1287 			last_delay = 250;
1288 		break;
1289 
1290 
1291 		default:
1292 		break;
1293 	}
1294 
1295 	last_e_sound = curr_e_sound;
1296 }
1297 
MoveEnemy(struct enemy * e)1298 void MoveEnemy(struct enemy *e)
1299 {
1300 	int n_gems;
1301 	int i;
1302 	int move_x, move_y;
1303 	int door_x=0, door_y=0;
1304 	int enemy_fire_type;
1305 	int actual_lives;
1306 	int can_move = 0;
1307 	struct RoomConnection *con_traverse;
1308 	struct RoomConnection *rcon;
1309 	int nearest;
1310 	struct bullet *b;
1311 	e->t++;
1312 	float dp;
1313 	float dpf;
1314 	if (e->teleport_v > 0) {
1315 		e->teleport_v--;
1316 		return;
1317 	}
1318 
1319 	if (e->enemy_type < 10) {
1320 		enemy_fire_type = e->enemy_type;
1321 	} else {
1322 		enemy_fire_type = rand()%10;
1323 	}
1324 
1325 	if (e->dying == 0) {
1326 		if ((e->t % e->fire_rate) == 0) {
1327 			if (e->room == player_room) {
1328 				switch (enemy_fire_type) {
1329 					case 0:
1330 						EnemySound(0, PlayerDist(e->x, e->y));
1331 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y), 1.5);
1332 						if (e->enemy_type==10) e->fire_rate = 20;
1333 					break;
1334 
1335 					case 1:
1336 						EnemySound(1, PlayerDist(e->x, e->y));
1337 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)+0.1, 2.1);
1338 						CreateBullet(e->x, e->y, e, 3, PlayerDir(e->x, e->y), 2.4);
1339 						CreateBullet(e->x, e->y, e, 3, PlayerDir(e->x, e->y)-0.1, 2.1);
1340 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y), 1.7);
1341 						if (e->enemy_type==10) e->fire_rate = 25;
1342 					break;
1343 
1344 					case 2:
1345 						EnemySound(2, PlayerDist(e->x, e->y));
1346 						for (dp = 0; dp < M_PI*2; dp += 0.25) {
1347 							CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)+dp, 1.1);
1348 						}
1349 						dp = RandomDir();
1350 						for (i = 0; i < 20; i++) {
1351 							CreateBullet(e->x, e->y, e, 0, dp, (float)i * 0.1 + 2.5);
1352 						}
1353 						if (e->enemy_type==10) e->fire_rate = 40;
1354 					break;
1355 
1356 					case 3:
1357 						EnemySound(3, PlayerDist(e->x, e->y));
1358 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y), 2.5);
1359 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)+0.1, 2.5);
1360 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)+0.2, 2.5);
1361 						CreateBullet(e->x, e->y, e, 1, PlayerDir(e->x, e->y), 1.5);
1362 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)-0.2, 2.2);
1363 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)-0.3, 2.2);
1364 						if (e->enemy_type==10) e->fire_rate = 24;
1365 					break;
1366 
1367 					case 4:
1368 						EnemySound(4, PlayerDist(e->x, e->y));
1369 						for (dp = 0; dp < M_PI * 0.66; dp += 0.2) {
1370 							CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)+0.5 - dp, 1.8+(dp/2));
1371 							CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)-0.4 + dp, 1.8+(dp/2));
1372 						}
1373 						FireLaser(e->x, e->y, e, PlayerDir(e->x, e->y), 24, 4, 20.0, 6);
1374 						if (e->enemy_type==10) e->fire_rate = 32;
1375 					break;
1376 
1377 					case 5:
1378 						EnemySound(5, PlayerDist(e->x, e->y));
1379 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y), 4);
1380 						if (e->enemy_type==10) e->fire_rate = 2;
1381 					break;
1382 
1383 					case 6:
1384 						EnemySound(6, PlayerDist(e->x, e->y));
1385 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)+0.25, 6);
1386 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)+0.25, 4);
1387 
1388 						CreateBullet(e->x, e->y, e, 5, PlayerDir(e->x, e->y) - 0.05, 4.99);
1389 						CreateBullet(e->x, e->y, e, 5, PlayerDir(e->x, e->y), 4.99);
1390 						CreateBullet(e->x, e->y, e, 5, PlayerDir(e->x, e->y) + 0.05, 4.99);
1391 
1392 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)-0.25, 5);
1393 						CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)-0.25, 3);
1394 						if (e->enemy_type==10) e->fire_rate = 10;
1395 					break;
1396 
1397 					case 7:
1398 						EnemySound(7, PlayerDist(e->x, e->y));
1399 						for (dp = 0; dp < M_PI * 0.66; dp += 0.1) {
1400 							CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)+0.5 - dp, 1.8+(dp/2));
1401 							CreateBullet(e->x, e->y, e, 3, PlayerDir(e->x, e->y)-0.4 + dp, 1.8+(dp/2));
1402 
1403 							CreateBullet(e->x, e->y, e, 3, PlayerDir(e->x, e->y)+0.5 - dp*2, 4+(dp*2));
1404 							CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y)-0.4 + dp*2, 4+(dp*2));
1405 						}
1406 						FireLaser(e->x, e->y, e, (float)e->t / 25.0, 16, 10, 0.08, 4);
1407 						FireLaser(e->x, e->y, e, (float)e->t / 25.0 + M_PI*2/4, 16, 10, 0.08, 4);
1408 						FireLaser(e->x, e->y, e, (float)e->t / 25.0 + M_PI*4/4, 16, 10, 0.08, 4);
1409 						FireLaser(e->x, e->y, e, (float)e->t / 25.0 + M_PI*6/4, 16, 10, 0.08, 4);
1410 						if (e->enemy_type==10) e->fire_rate = 27;
1411 					break;
1412 
1413 					case 8:
1414 						EnemySound(8, PlayerDist(e->x, e->y));
1415 						for (dp = 0; dp < 1; dp += 0.1) {
1416 							CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y) + M_PI/2 + dp, 3 + dp/2);
1417 							CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y), 4 + dp);
1418 							CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y) - M_PI/2 - dp, 3 + dp/2);
1419 						}
1420 						CreateBullet(e->x, e->y, e, 6, (e->t / e->fire_rate)*0.7, 2);
1421 						if (e->enemy_type==10) e->fire_rate = 8;
1422 					break;
1423 
1424 					case 9:
1425 					    i = rand()%((rand()%(PlayerDist(e->x, e->y)+1))+1);
1426 					    if (i < 15) {
1427 							EnemySound(9, PlayerDist(e->x, e->y));
1428 							dpf = (float)(2000 - e->str) / 2500.0;
1429 							for (dp = 0; dp < 1; dp += dpf) {
1430 								(CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y) + 0.1 - dp/5.0, 3.5 + dp/3.0));
1431 								CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y) + (2*M_PI / 3) + 0.1 - dp/5.0, 3.5 + dp/3.0);
1432 								CreateBullet(e->x, e->y, e, 0, PlayerDir(e->x, e->y) + (4*M_PI / 3) + 0.1 - dp/5.0, 3.5 + dp/3.0);
1433 
1434 								CreateBullet(e->x, e->y, e, 4, PlayerDir(e->x, e->y) + 0.1 - dp/5.0, 7 + dp*5);
1435 								CreateBullet(e->x, e->y, e, 4, PlayerDir(e->x, e->y) + (2*M_PI / 3) + 0.1 - dp/5.0, 7 + dp*5);
1436 								CreateBullet(e->x, e->y, e, 4, PlayerDir(e->x, e->y) + (4*M_PI / 3) + 0.1 - dp/5.0, 7 + dp*5);
1437 							}
1438 						}
1439 						if (e->enemy_type==10) e->fire_rate = 21;
1440 					break;
1441 
1442 					default:
1443 					break;
1444 				}
1445 			}
1446 		}
1447 
1448 		if ((e->t % e->speed) == 0) {
1449 			if (player_room == e->room) {
1450 				e->m_exit = NULL;
1451 				if (e->t % (e->speed * (8 + rand()%6)) == 0) {
1452 					e->move_dir = (float)(rand()%256) / 256.0 * M_PI * 2.0;
1453 				}
1454 				move_x = e->x + cos(e->move_dir)*5;
1455 				move_y = e->y + sin(e->move_dir)*5;
1456 
1457 				EnemyMovement(e, move_x, move_y);
1458 			} else {
1459 				if (CanLeaveRoom(e->room)) {
1460 					// Try to follow the player into the next room
1461 
1462 					// Are we already moving towards an exit?
1463 
1464 					if (e->m_exit != NULL) {
1465 						rcon = e->m_exit;
1466 
1467 						door_x = (rcon->x + (rcon->x - rcon->x2))*32+16;
1468 						door_y = (rcon->y + (rcon->y - rcon->y2))*32+16;
1469 
1470 						can_move = 1;
1471 					} else {
1472 						con_traverse = rooms[e->room].con;
1473 						nearest = PlayerDist(e->x, e->y);
1474 						rcon = NULL;
1475 						while (con_traverse != NULL) {
1476 							i = PlayerDist(con_traverse->x2 * 32 + 16, con_traverse->y2 * 32 + 16);
1477 
1478 							if ((i < nearest) && CanEnterRoom(GetRoom(con_traverse->x2, con_traverse->y2))) {
1479 								nearest = i;
1480 								rcon = con_traverse;
1481 							}
1482 							con_traverse = con_traverse->n;
1483 						}
1484 
1485 						if (rcon != NULL) {
1486 							door_x = (rcon->x + (rcon->x - rcon->x2))*32+16;
1487 							door_y = (rcon->y + (rcon->y - rcon->y2))*32+16;
1488 							e->m_exit = rcon;
1489 							can_move = 1;
1490 						}
1491 					}
1492 
1493 					// So, can we move?
1494 					if (can_move) {
1495 						// Are we near the door?
1496 						if (( abs(door_x - e->x) + abs(door_y - e->y))<6) {
1497 							// Go through the door
1498 							e->last_room = e->room;
1499 							e->p_last_room = player_room;
1500 							e->x = (rcon->x2 + (rcon->x2 - rcon->x))*32+16;
1501 							e->y = (rcon->y2 + (rcon->y2 - rcon->y))*32+16;
1502 							rooms[e->room].enemies--;
1503 							e->room = (rcon->c);
1504 							rooms[e->room].enemies++;
1505 							e->curr_follow = -1;
1506 
1507 							e->m_exit = NULL;
1508 
1509 						} else {
1510 							// Move towards the door
1511 							e->move_dir = atan2(door_y - e->y, door_x - e->x);
1512 							move_x = e->x + cos(e->move_dir)*5;
1513 							move_y = e->y + sin(e->move_dir)*5;
1514 
1515 							EnemyMovement(e, move_x, move_y);
1516 						}
1517 					}
1518 				}
1519 			}
1520 		}
1521 	}
1522 
1523 	if (e->dying > 0) {
1524 		e->dying++;
1525 		if (e->dying == 3) {
1526 			b = bullet_stack;
1527 			while (b != NULL) {
1528 				if (!b->delete_me) {
1529 					if (b->firer == e) {
1530 						b->delete_me = 1;
1531 						CreateGem(b->x, b->y, b->room, (e->max_gems + e->min_gems) / 5 + (artifacts[2] * (e->max_gems + e->min_gems) / 4));
1532 					}
1533 				}
1534 				b = b->next;
1535 			}
1536 		}
1537 		if (e->dying >= 20) {
1538 			if ((e->lives >= 4)&&training) {
1539 				actual_lives = e->lives * 3 / 4;
1540 			} else {
1541 				actual_lives = e->lives;
1542 			}
1543 
1544 			e->deaths++;
1545 			if (e->deaths >= actual_lives) {
1546 				e->deaths--;
1547 				e->delete_me = 1;
1548 				e->dying = 0;
1549 				killed_enemies++;
1550 				rooms[e->room].enemies--;
1551 				n_gems = e->min_gems + rand()%(e->max_gems - e->min_gems + 1);
1552 				for (i = 0; i < n_gems; i++) {
1553 					CreateGem(e->x - 16 + rand()%32, e->y - 16 + rand()%32, e->room, 1+rand()%4 + (artifacts[2]*rand()%3));
1554 				}
1555 				if (rooms[e->room].room_type == 3) {
1556 					ArtifactRoomUnlock(e->room);
1557 				}
1558 			} else {
1559 				e->dying = 0;
1560 			}
1561 		}
1562 	}
1563 }
1564 
MoveBullet(struct bullet * e)1565 void MoveBullet(struct bullet *e)
1566 {
1567 	int pdist;
1568 	struct bullet *n;
1569 	float fx, fy;
1570 	static int last_shield_hit_sound = 0;
1571 	int c_shield_hit_sound;
1572 
1573 	e->t++;
1574 
1575 	if ( (boss_fight_mode != 0) && (boss_fight_mode != 2) && (e->dying == 0) ) {
1576 		e->dying = 1;
1577 	}
1578 
1579 	if (e->dying == 0) {
1580 		if (e->img == 7) {
1581 			if (proxy_seek) {
1582 				e->speed = 10;
1583 				e->img = 4;
1584 				e->dir = (e->dir + PlayerDir(e->x, e->y)) / 2;
1585 			}
1586 		}
1587 
1588 		e->x += cos(e->dir) * e->speed;
1589 		e->y += sin(e->dir) * e->speed;
1590 
1591 		if (e->img == 1) {
1592 			if (e->t % 20 == 19) {
1593 				if (e->t % 40 >= 20)
1594 					CreateBullet(e->x, e->y, e->firer, 3, e->dir + M_PI/2, e->speed * 0.75);
1595 				else
1596 					CreateBullet(e->x, e->y, e->firer, 3, e->dir - M_PI/2, e->speed * 0.75);
1597 			}
1598 		}
1599 		if (e->img == 6) {
1600 			if (e->t % 40 == 39) {
1601 				(FireLaser(e->x, e->y, e->firer, (float)e->t / 30.0, 20, 10, 0.05, 2))->parent = e;
1602 				(FireLaser(e->x, e->y, e->firer, (float)e->t / 30.0 + M_PI*2/3, 20, 10, 0.05, 2))->parent = e;
1603 				(FireLaser(e->x, e->y, e->firer, (float)e->t / 30.0 + M_PI*4/3, 20, 10, 0.05, 2))->parent = e;
1604 			}
1605 		}
1606 
1607 
1608 		if (e->img == 5) {
1609 			if (e->t < 100) {
1610 				if (e->t % 20 == 9) {
1611 					n = CreateBullet(e->x, e->y, e->firer, 5, e->dir + M_PI/4, e->speed);
1612 					n->natural_dir = e->dir;
1613 					n->t = e->t;
1614 					e->natural_dir = e->dir;
1615 
1616 					e->dir -= M_PI / 4;
1617 				}
1618 				if (e->t % 20 == 19) {
1619 					e->dir = e->natural_dir;
1620 				}
1621 			}
1622 			if (e->t == 100) {
1623 				e->dir = PlayerDir(e->x, e->y);
1624 				e->speed *= 1.5;
1625 			}
1626 		}
1627 
1628 		if (IsSolid(Get(e->x/32, e->y/32))) {
1629 			if (e->img == 3) {
1630 				if (e->room == player_room) {
1631 					e->dir = PlayerDir(e->x, e->y);
1632 
1633 					if (IsSolid(Get((e->x + cos(e->dir) * e->speed * 1.5)/32, (e->y + sin(e->dir) * e->speed * 1.5)/32))) e->dying = 1;
1634 
1635 				} else {
1636 					e->dying = 1;
1637 				}
1638 			} else {
1639 				e->dying = 1;
1640 			}
1641 		}
1642 
1643 		if (e->img == 2) {
1644 			if (e->parent != NULL) {
1645 				e->x = e->parent->x;
1646 				e->y = e->parent->y;
1647 			} else {
1648 				if (e->firer != NULL) {
1649 					e->x = e->firer->x;
1650 					e->y = e->firer->y;
1651 				}
1652 			}
1653 			if (e->dying == 0) {
1654 				if ((e->t > e->fire_time)&&(e->t <= (e->fire_time + e->duration))) {
1655 					fx = e->x;
1656 					fy = e->y;
1657 					while (!IsSolid(Get((fx)/32, (fy)/32))) {
1658 						if (player_dying == 0) {
1659 							if (PlayerDist(fx, fy) < 30) {
1660 								// hits player shield
1661 								if ((player_shield > 0)&&(shield_hp > 0)) {
1662 									shield_hp -= e->shield_damage;
1663 									if (shield_hp >= 0) {
1664 										e->dying = 1;
1665 										break;
1666 									} else {
1667 										shield_hp = 0;
1668 									}
1669 								}
1670 
1671 								if (PlayerDist(fx, fy) < 4 - (2 * artifacts[5])) {
1672 									player_dying = 1;
1673 									SND_Pos("/usr/local/share/meritous/a/playerhurt.wav", 128, 0);
1674 									e->dying = 1;
1675 									break;
1676 								}
1677 							}
1678 						}
1679 						fx += cos(e->dir)*2;
1680 						fy += sin(e->dir)*2;
1681 					}
1682 				}
1683 				if (e->turn > 10) {
1684 					if (e->dir > PlayerDir(e->x, e->y)) {
1685 						e->dir -= (e->dir - PlayerDir(e->x, e->y)) / (e->turn - 9.00);
1686 						e->dir -= (e->dir - PlayerDir(e->x, e->y)) / (e->turn - 9.00);
1687 					} else {
1688 						e->dir += (PlayerDir(e->x, e->y) - e->dir) / (e->turn - 9.00);
1689 					}
1690 				} else {
1691 					e->dir += e->turn;
1692 				}
1693 				if (e->t > (e->fire_time + e->duration)) {
1694 					e->dying = 1;
1695 				}
1696 			}
1697 		} else {
1698 
1699 			pdist = PlayerDist(e->x, e->y);
1700 
1701 			if (pdist < 30) {
1702 				if (player_dying == 0) {
1703 					if (player_shield > 0) {
1704 						if (shield_hp > 0) {
1705 							shield_hp--;
1706 							if (e->img == 4) {
1707 								e->dying = 1;
1708 							} else {
1709 								e->dir += M_PI;
1710 								c_shield_hit_sound = SDL_GetTicks();
1711 
1712 								if ((c_shield_hit_sound - 150) > last_shield_hit_sound) {
1713 									SND_Pos("/usr/local/share/meritous/a/shieldhit.wav", 50, 0);
1714 									last_shield_hit_sound = c_shield_hit_sound;
1715 								}
1716 								while (PlayerDist(e->x, e->y) < 30) {
1717 									e->x += cos(e->dir) * e->speed;
1718 									e->y += sin(e->dir) * e->speed;
1719 								}
1720 							}
1721 						}
1722 					}
1723 				}
1724 			}
1725 			if (e->dying == 0) {
1726 				if (pdist < 6 - (2 * artifacts[5])) {
1727 					if (player_dying == 0) {
1728 						SND_Pos("/usr/local/share/meritous/a/playerhurt.wav", 128, 0);
1729 						player_dying = 1;
1730 					}
1731 				}
1732 			}
1733 		}
1734 	}
1735 
1736 	if ((e->dying == 1) && (e->img == 8)) {
1737 		SpawnLaser(e->x - cos(e->dir) * e->speed, e->y - sin(e->dir) * e->speed, PlayerDir(e->x, e->y), 10, 10, 0.0, player_shield / 6);
1738 	}
1739 
1740 	if (GetRoom((e->x)/32, (e->y)/32) != e->room) {
1741 		e->delete_me = 1;
1742 	}
1743 
1744 	if (e->dying > 0) {
1745 		e->dying++;
1746 
1747 		if (e->dying >= 10) {
1748 			e->delete_me = 1;
1749 			e->dying = 0;
1750 		}
1751 	}
1752 }
1753 
DrawEnemy(struct enemy * e,SDL_Surface * scr)1754 void DrawEnemy(struct enemy *e, SDL_Surface *scr)
1755 {
1756 	SDL_Rect draw_pos;
1757 	SDL_Rect surf_pos;
1758 	static SDL_Surface *teleflash = NULL;
1759 
1760 	if (e->delete_me) return;
1761 	draw_pos.x = e->x - e->image->h/2/e->lives - scroll_x;
1762 	draw_pos.y = e->y - e->image->h/2/e->lives - scroll_y;
1763 
1764 	surf_pos.x = e->blit_pos;
1765 	surf_pos.y =  e->image->h/e->lives*e->deaths;
1766 	surf_pos.w = e->image->h/e->lives;
1767 	surf_pos.h = e->image->h/e->lives;
1768 
1769 	if (e->teleport_v < 8) {
1770 
1771 		if (e->dying == 0) {
1772 			SDL_BlitSurface(e->image, &surf_pos, scr, &draw_pos);
1773 		} else {
1774 			if ((e->deaths+1) >= e->lives) {
1775 				surf_pos.w = e->image->h/e->lives * (20 - e->dying) / 20;
1776 				surf_pos.h = surf_pos.w;
1777 				surf_pos.x += (e->image->h/e->lives - surf_pos.w)/2;
1778 				surf_pos.y += (e->image->h/e->lives - surf_pos.w)/2;
1779 				draw_pos.x += (e->image->h/e->lives - surf_pos.w)/2;
1780 				draw_pos.y += (e->image->h/e->lives - surf_pos.w)/2;
1781 			} else {
1782 				surf_pos.w = e->image->h/e->lives * (20 - e->dying/2) / 20;
1783 				surf_pos.h = surf_pos.w;
1784 				surf_pos.x += (e->image->h/e->lives - surf_pos.w)/2;
1785 				surf_pos.y += (e->image->h/e->lives - surf_pos.w)/2;
1786 				draw_pos.x += (e->image->h/e->lives - surf_pos.w)/2;
1787 				draw_pos.y += (e->image->h/e->lives - surf_pos.w)/2;
1788 			}
1789 			SDL_BlitSurface(e->image, &surf_pos, scr, &draw_pos);
1790 		}
1791 
1792 		if (((e->t % 8) == 1) && (!game_paused)) {
1793 			e->blit_pos = (e->blit_pos + e->image->h/e->lives) % e->image->w;
1794 		}
1795 
1796 		draw_pos.x = e->x - e->image->h/e->lives/2 - scroll_x;
1797 		draw_pos.y = e->y - e->image->h/e->lives/2 - scroll_y;
1798 
1799 		draw_pos.x -= (128-e->image->h/e->lives)/2;
1800 		draw_pos.y -= (128-e->image->h/e->lives)/2;
1801 
1802 		if (magic_circuit >= e->str) {
1803 			SDL_BlitSurface(reticle, NULL, scr, &draw_pos);
1804 		}
1805 
1806 		draw_pos.x = e->x - e->image->h/e->lives/2 - scroll_x;
1807 		draw_pos.y = e->y - e->image->h/e->lives/2 - scroll_y;
1808 
1809 		draw_pos.x -= (128-e->image->h/e->lives)/2;
1810 		draw_pos.y -= (128-e->image->h/e->lives)/2;
1811 
1812 		if (sqrt(sqr(e->x - player_x) + sqr(e->y - player_y)) < circuit_range) {
1813 			SDL_BlitSurface(inrange, NULL, scr, &draw_pos);
1814 		}
1815 	}
1816 
1817 	if (e->teleport_v < 24) {
1818 		if (teleflash == NULL) {
1819 			teleflash = IMG_Load("/usr/local/share/meritous/i/teleflash.png");
1820 			SDL_SetColorKey(teleflash, SDL_SRCCOLORKEY | SDL_RLEACCEL, 0);
1821 		}
1822 
1823 		surf_pos.x = 48*((e->teleport_v) / 3);
1824 		surf_pos.y = 0;
1825 		surf_pos.w = 48;
1826 		surf_pos.h = 48;
1827 
1828 		draw_pos.x = e->x - 24 - scroll_x;
1829 		draw_pos.y = e->y - 24 - scroll_y;
1830 		SDL_BlitSurface(teleflash, &surf_pos, scr, &draw_pos);
1831 	}
1832 }
1833 
DrawBullet(struct bullet * b)1834 void DrawBullet(struct bullet *b)
1835 {
1836 	int i;
1837 	int x1, y1, x2, y2, xo1, yo1;
1838 	int z;
1839 	float fx, fy;
1840 	static SDL_Surface *d_star_small = NULL, *d_star_big = NULL, *d_star_ls = NULL;
1841 	SDL_Rect draw_pos, surf_pos;
1842 	if (b->delete_me) return;
1843 	if (b->img == 0) {
1844 		if (b->dying > 0) {
1845 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 6+(b->dying / 2), b->dying*10);
1846 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 3+(b->dying / 2), 255-b->dying*10);
1847 		} else {
1848 			if ((b->t % 8) < 4) {
1849 				DrawCircle(b->x - scroll_x, b->y - scroll_y, 6, 0);
1850 				DrawCircle(b->x - scroll_x, b->y - scroll_y, 4, 255);
1851 			} else {
1852 				DrawCircle(b->x - scroll_x, b->y - scroll_y, 6, 255);
1853 				DrawCircle(b->x - scroll_x, b->y - scroll_y, 4, 0);
1854 			}
1855 		}
1856 	}
1857 	if (b->img == 1) {
1858 		if (d_star_big == NULL) {
1859 			d_star_big = IMG_Load("/usr/local/share/meritous/i/star1.png");
1860 			SDL_SetColorKey(d_star_big, SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
1861 		}
1862 
1863 		if (b->dying == 0) {
1864 			surf_pos.x = b->x - 16 - scroll_x;
1865 			surf_pos.y = b->y - 16 - scroll_y;
1866 			draw_pos.x = (b->t % 8)*32;
1867 			draw_pos.y = 0;
1868 			draw_pos.w = 32;
1869 			draw_pos.h = 32;
1870 			SDL_BlitSurface(d_star_big, &draw_pos, screen, &surf_pos);
1871 		} else {
1872 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 4+(b->dying), b->dying*10);
1873 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 2+(b->dying), 255-b->dying*10);
1874 		}
1875 	}
1876 	if (b->img == 2) {
1877 		// IMMA CHARGIN MAH LAZER
1878 		if (b->t <= b->fire_time) {
1879 			z = (b->t * 150 / (b->fire_time+1)) + 80;
1880 
1881 			fx = b->x;
1882 			fy = b->y;
1883 			while (!IsSolid(Get((fx)/32, (fy)/32))) {
1884 				DrawRect(fx-1-scroll_x, fy-1-scroll_y, 4, 4, z/2);
1885 				fx += cos(b->dir)*2;
1886 				fy += sin(b->dir)*2;
1887 
1888 				if ((player_shield > 0)&&(shield_hp > 0)&&(PlayerDist(fx, fy) < 30)) break;
1889 				if (PlayerDist(fx, fy) < 4) break;
1890 			}
1891 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 5, (z+255)/2.4);
1892 			DrawCircle(fx-cos(b->dir)*2 - scroll_x, fy-sin(b->dir)*2 - scroll_y, 4, z/2);
1893 
1894 			fx = b->x;
1895 			fy = b->y;
1896 			while (!IsSolid(Get((fx)/32, (fy)/32))) {
1897 				DrawRect(fx-scroll_x, fy-scroll_y, 2, 2, z);
1898 				fx += cos(b->dir)*2;
1899 				fy += sin(b->dir)*2;
1900 
1901 				if ((player_shield > 0)&&(shield_hp > 0)&&(PlayerDist(fx, fy) < 30)) break;
1902 				if (PlayerDist(fx, fy) < 4) break;
1903 			}
1904 
1905 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 3, (z+255)/2);
1906 			DrawCircle(fx-cos(b->dir)*2 - scroll_x, fy-sin(b->dir)*2 - scroll_y, 2, z);
1907 		}
1908 
1909 		// SHOOP DA WHOOP
1910 		if ((b->t > b->fire_time) && (b->t <= b->fire_time + b->duration)) {
1911 			z = 255 - ((b->t - b->fire_time) * 200 / (b->duration+1));
1912 
1913 			fx = b->x;
1914 			fy = b->y;
1915 			while (!IsSolid(Get((fx)/32, (fy)/32))) {
1916 				DrawRect(fx-3-scroll_x, fy-3-scroll_y, 8, 8, z*2/3);
1917 				fx += cos(b->dir)*2;
1918 				fy += sin(b->dir)*2;
1919 
1920 				if ((player_shield > 0)&&(shield_hp > 0)&&(PlayerDist(fx, fy) < 30)) break;
1921 				if (PlayerDist(fx, fy) < 4) break;
1922 			}
1923 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 9, (z+255)/2.4);
1924 			DrawCircle(fx-cos(b->dir)*2 - scroll_x, fy-sin(b->dir)*2 - scroll_y, 8, z*2/3);
1925 			fx = b->x;
1926 			fy = b->y;
1927 			while (!IsSolid(Get((fx)/32, (fy)/32))) {
1928 				DrawRect(fx-2-scroll_x, fy-2-scroll_y, 6, 6, z);
1929 				fx += cos(b->dir)*2;
1930 				fy += sin(b->dir)*2;
1931 
1932 				x1 = fx + rand()%12 - rand()%12 - scroll_x;
1933 				y1 = fy + rand()%12 - rand()%12 - scroll_y;
1934 				DrawRect(x1, y1, 2, 2, rand()%(z+1));
1935 
1936 				if ((player_shield > 0)&&(shield_hp > 0)&&(PlayerDist(fx, fy) < 30)) break;
1937 				if (PlayerDist(fx, fy) < 4) break;
1938 			}
1939 
1940 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 7, (z+255)/2);
1941 			DrawCircle(fx-cos(b->dir)*2 - scroll_x, fy-sin(b->dir)*2 - scroll_y, 6, z);
1942 		}
1943 	}
1944 	if (b->img == 3) {
1945 		if (d_star_small == NULL) {
1946 			d_star_small = IMG_Load("/usr/local/share/meritous/i/star2.png");
1947 			SDL_SetColorKey(d_star_small, SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
1948 		}
1949 		if (b->dying == 0) {
1950 			surf_pos.x = b->x - 8 - scroll_x;
1951 			surf_pos.y = b->y - 8 - scroll_y;
1952 			draw_pos.x = (b->t % 8)*16;
1953 			draw_pos.y = 0;
1954 			draw_pos.w = 16;
1955 			draw_pos.h = 16;
1956 			SDL_BlitSurface(d_star_small, &draw_pos, screen, &surf_pos);
1957 		} else {
1958 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 4+(b->dying/2), b->dying*10);
1959 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 2+(b->dying/2), 255-b->dying*10);
1960 		}
1961 	}
1962 	if (b->img == 4) {
1963 		if (b->dying == 0) {
1964 			x1 = b->x + cos(b->dir)*(2) - scroll_x;
1965 			y1 = b->y + sin(b->dir)*(2) - scroll_y;
1966 
1967 			x2 = b->x - cos(b->dir)*(80) - scroll_x;
1968 			y2 = b->y - sin(b->dir)*(80) - scroll_y;
1969 			for (i = 0; i < 40; i++) {
1970 				xo1 = (x2 - x1)*i/40 + x1;
1971 				yo1 = (y2 - y1)*i/40 + y1;
1972 
1973 				z = (i/2);
1974 				if (i > 10) z = (40 - i)/7;
1975 
1976 				DrawRect(xo1 - z - 2, yo1 - z - 2, z*2 + 4, z*2 + 4, 200);
1977 			}
1978 			for (i = 0; i < 40; i++) {
1979 				xo1 = (x2 - x1)*i/40 + x1;
1980 				yo1 = (y2 - y1)*i/40 + y1;
1981 
1982 				z = (i/2);
1983 				if (i > 10) z = (40 - i)/7;
1984 
1985 				DrawRect(xo1 - z, yo1 - z, z*2, z*2, 255);
1986 			}
1987 		} else{
1988 			DrawCircleEx(b->x - scroll_x, b->y - scroll_y, b->dying * 2 + 1, b->dying * 1.75 - 1, 230);
1989 			DrawCircleEx(b->x - scroll_x, b->y - scroll_y, b->dying * 2, b->dying * 1.75, 255);
1990 		}
1991 	}
1992 	if (b->img == 5) {
1993 		if (b->dying > 0) {
1994 			i = 4+(b->dying / 5);
1995 			DrawRect(b->x - scroll_x - (i-1/2), b->y - scroll_y - (i-1/2), i, i, b->dying*10);
1996 			i = 2+(b->dying / 5);
1997 			DrawRect(b->x - scroll_x - (i-1/2), b->y - scroll_y - (i-1/2), i, i, 255-b->dying*10);
1998 		} else {
1999 			if ((b->t % 8) < 4) {
2000 				DrawRect(b->x - scroll_x - 1, b->y - scroll_y - 1, 4, 4, 0);
2001 				DrawRect(b->x - scroll_x, b->y - scroll_y, 2, 2, 255);
2002 			} else {
2003 				DrawRect(b->x - scroll_x - 1, b->y - scroll_y - 1, 4, 4, 255);
2004 				DrawRect(b->x - scroll_x, b->y - scroll_y, 2, 2, 0);
2005 			}
2006 		}
2007 	}
2008 	if (b->img == 6) {
2009 		if (d_star_ls == NULL) {
2010 			d_star_ls = IMG_Load("/usr/local/share/meritous/i/star3.png");
2011 			SDL_SetColorKey(d_star_ls, SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
2012 		}
2013 		if (b->dying == 0) {
2014 			surf_pos.x = b->x - 16 - scroll_x;
2015 			surf_pos.y = b->y - 16 - scroll_y;
2016 			draw_pos.x = (b->t % 8)*32;
2017 			draw_pos.y = 0;
2018 			draw_pos.w = 32;
2019 			draw_pos.h = 32;
2020 			SDL_BlitSurface(d_star_ls, &draw_pos, screen, &surf_pos);
2021 		} else {
2022 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 4+(b->dying), 255-b->dying*10);
2023 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 2+(b->dying), b->dying*10);
2024 		}
2025 	}
2026 
2027 	if (b->img == 7) {
2028 		if ((b->t % 8) < 4) {
2029 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 8, 0);
2030 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 5, 255);
2031 		} else {
2032 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 8, 255);
2033 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 5, 0);
2034 		}
2035 	}
2036 	if (b->img == 8) {
2037 		if (b->dying > 0) {
2038 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 12+(b->dying), b->dying*10);
2039 			DrawCircle(b->x - scroll_x, b->y - scroll_y, 6+(b->dying), 255-b->dying*10);
2040 		} else {
2041 			if ((b->t % 6) < 3) {
2042 				DrawCircle(b->x - scroll_x, b->y - scroll_y, 12, 0);
2043 				DrawCircle(b->x - scroll_x, b->y - scroll_y, 8, 255);
2044 			} else {
2045 				DrawCircle(b->x - scroll_x, b->y - scroll_y, 12, 255);
2046 				DrawCircle(b->x - scroll_x, b->y - scroll_y, 8, 0);
2047 			}
2048 		}
2049 	}
2050 }
2051 
DrawGem(struct diamond * g)2052 void DrawGem(struct diamond *g)
2053 {
2054 	static SDL_Surface *d_sprite = NULL;
2055 	int gemtype = 0;
2056 	static char hp_icon[2];
2057 	SDL_Rect draw_pos;
2058 	SDL_Rect surf_pos;
2059 	unsigned char fxp = (SDL_GetTicks() / 300)%2 ? 255 : 0;
2060 
2061 	if (g->delete_me) return;
2062 
2063 	if (d_sprite == NULL) {
2064 		d_sprite = IMG_Load("/usr/local/share/meritous/i/gem.png");
2065 		SDL_SetColorKey(d_sprite, SDL_SRCCOLORKEY | SDL_RLEACCEL, 255);
2066 		hp_icon[0] = 3;
2067 		hp_icon[1] = 0;
2068 	}
2069 
2070 	if (g->value == 1) gemtype = 2;
2071 	if ((g->value > 1)&&(g->value < 5)) gemtype = 1;
2072 	if (g->value >= 5) gemtype = 0;
2073 
2074 	if (g->value != 31337) {
2075 
2076 		surf_pos.x = g->x - 4 - scroll_x;
2077 		surf_pos.y = g->y - 4 - scroll_y;
2078 		draw_pos.x = (g->t % 4) * 8 + 32 * gemtype;
2079 		draw_pos.y = 0;
2080 		draw_pos.w = 8;
2081 		draw_pos.h = 8;
2082 
2083 		SDL_BlitSurface(d_sprite, &draw_pos, screen, &surf_pos);
2084 	} else {
2085 		DrawCircle(g->x - scroll_x, g->y - scroll_y, 6, (rand()%64) ^ fxp);
2086 		draw_text(g->x - 4 - scroll_x, g->y - 4 - scroll_y, hp_icon, (200+rand()%56) ^ fxp);
2087 	}
2088 
2089 	g->t++;
2090 }
2091 
xprintf(char * s)2092 void xprintf(char *s)
2093 {
2094 	printf(s);
2095 	fflush(stdout);
2096 }
2097 
DrawInvisible(int x,int y)2098 void DrawInvisible(int x, int y)
2099 {
2100 	SDL_Rect dest;
2101 	dest.x = x - scroll_x - 24;
2102 	dest.y = y - scroll_y - 24;
2103 	SDL_BlitSurface(invis_enemy, NULL, screen, &dest);
2104 }
2105 
DrawEntities()2106 void DrawEntities()
2107 {
2108 	struct enemy *t;
2109 	struct bullet *b;
2110 	struct diamond *g;
2111 	struct enemyloc *els;
2112 
2113 	if ((rooms[player_room].room_type != 3)&&(rooms[player_room].room_type != 2)) {
2114 		// Draw gems
2115 
2116 		g = room_gems[player_room];
2117 		while (g != NULL) {
2118 			if ((g->room == player_room)&&(g->delete_me == 0)&&(g->value != 31337)) {
2119 				DrawGem(g);
2120 			}
2121 			g = g->next_in_room;
2122 		}
2123 		g = room_gems[player_room];
2124 		while (g != NULL) {
2125 			if ((g->room == player_room)&&(g->delete_me == 0)&&(g->value == 31337)) {
2126 				DrawGem(g);
2127 			}
2128 			g = g->next_in_room;
2129 		}
2130 	}
2131 
2132 	t = active_stack;
2133 	while (t != NULL) {
2134 		if (!t->delete_me) {
2135 			if ((t->room == player_room) && (t->enemy_type != 9)) {
2136 				DrawEnemy(t, screen);
2137 			}
2138 		}
2139 		t = t->next_active;
2140 	}
2141 
2142 	// Draw invisible enemies (if possible)
2143 	if (artifacts[6]) {
2144 		// Draw the actives
2145 		t = active_stack;
2146 		while (t != NULL) {
2147 			if (!t->delete_me)
2148 			{
2149 				if (((!t->delete_me)&&((t->room != player_room)||(t->enemy_type == 9)))) {
2150 					DrawInvisible(t->x, t->y);
2151 				}
2152 			}
2153 			t = t->next_active;
2154 		}
2155 		// Draw the inactives
2156 		if (!artifacts[11]) {
2157 			els = GetEnemyLoc(scroll_x, scroll_y);
2158 			while (els != NULL) {
2159 				t = els->e;
2160 				if (((!t->delete_me)&&((t->room != player_room)||(t->enemy_type == 9)))&&(t->active == 0)) {
2161 					if ((t->x+24 >= scroll_x) && (t->y+24 >= scroll_y)) {
2162 						if (t->x-24 <= (scroll_x+639)) {
2163 							if (t->y-24 <= (scroll_y+479)) {
2164 								if ((rooms[t->room].room_type != 2) && (rooms[t->room].room_type != 3)) {
2165 									DrawInvisible(t->x, t->y);
2166 								}
2167 							}
2168 						}
2169 					}
2170 				}
2171 				els = els->n;
2172 			}
2173 		}
2174 	}
2175 
2176 	b = bullet_stack;
2177 	while (b != NULL) {
2178 		if (!b->delete_me) {
2179 			if (b->room == player_room) {
2180 				DrawBullet(b);
2181 			}
2182 		}
2183 		b = b->next;
2184 	}
2185 }
2186 
MoveEntities()2187 void MoveEntities()
2188 {
2189 	struct enemy *t;
2190 	struct bullet *b;
2191 	struct diamond *g;
2192 
2193 	struct bullet *b_del;
2194 	struct diamond *g_del;
2195 
2196 	if ((rooms[player_room].room_type != 3)&&(rooms[player_room].room_type != 2)) {
2197 		// gem stuff
2198 		g = room_gems[player_room];
2199 		while (g != NULL) {
2200 			if ((g->room == player_room)&&(g->delete_me == 0)) {
2201 				if (artifacts[7]) {
2202 					g->x += (player_x+4 - g->x)/10;
2203 					g->y += (player_y+12 - g->y)/10;
2204 				}
2205 				if (PlayerDist(g->x, g->y) < 20) {
2206 					g->delete_me = 1;
2207 					total_gems--;
2208 
2209 					if (g->value == 31337) {
2210 						if (player_hp < (3 + (player_shield == 30)*3)) {
2211 							SND_Pos("/usr/local/share/meritous/a/crystal.wav", 64, 0);
2212 							player_hp++;
2213 						} else {
2214 							if (!training) {
2215 								SND_Pos("/usr/local/share/meritous/a/tone.wav", 64, 0);
2216 
2217 								if (player_lives == 1) {
2218 									player_lives_part += 15;
2219 								} else {
2220 									if (player_lives < 10) {
2221 										player_lives_part += 4;
2222 									} else {
2223 										player_lives_part += 1;
2224 									}
2225 								}
2226 								if (player_lives_part >= 88) {
2227 									player_lives_part -= 88;
2228 									player_lives += 1;
2229 									SND_Pos("/usr/local/share/meritous/a/crystal2.wav", 100, 0);
2230 								}
2231 							}
2232 						}
2233 
2234 					} else {
2235 						player_gems += g->value;
2236 					}
2237 				}
2238 			}
2239 			g = g->next_in_room;
2240 		}
2241 	}
2242 
2243 	t = active_stack;
2244 	while (t != NULL) {
2245 		if (!t->delete_me) {
2246 			if ((rooms[t->room].room_type != 3) || (t->room == player_room))
2247 				MoveEnemy(t);
2248 		}
2249 		t = t->next_active;
2250 	}
2251 
2252 	b = bullet_stack;
2253 	while (b != NULL) {
2254 		if (!b->delete_me) {
2255 			MoveBullet(b);
2256 		}
2257 		b = b->next;
2258 	}
2259 
2260 	// delete old bullets
2261 	b = bullet_stack;
2262 	if ((b != NULL)&&(b->delete_me)) {
2263 		b_del = b;
2264 		b = b->next;
2265 		free(b_del);
2266 		bullet_stack = b;
2267 	}
2268 	while (b != NULL) {
2269 		if (b->next != NULL) {
2270 			if (b->next->delete_me) {
2271 				b_del = b->next;
2272 
2273 				b->next = b->next->next;
2274 				free(b_del);
2275 			}
2276 		}
2277 		b = b->next;
2278 	}
2279 
2280 	// delete old gems
2281 	g = gem_stack;
2282 	if ((g != NULL)&&(g->delete_me)) {
2283 		// Remove room reference
2284 
2285 		if (g == room_gems[g->room]) {
2286 			room_gems[g->room] = g->next_in_room;
2287 			if (room_gems[g->room] != NULL) {
2288 				room_gems[g->room]->prv_in_room = NULL;
2289 			}
2290 		} else {
2291 			if (g->prv_in_room != NULL) {
2292 				g->prv_in_room->next_in_room = g->next_in_room;
2293 			}
2294 
2295 			if (g->next_in_room != NULL) {
2296 				g->next_in_room->prv_in_room = g->prv_in_room;
2297 			}
2298 		}
2299 
2300 		g_del = g;
2301 		g = g->next;
2302 		free(g_del);
2303 		gem_stack = g;
2304 	}
2305 	while (g != NULL) {
2306 		if (g->next != NULL) {
2307 			if (g->next->delete_me) {
2308 				// Remove room reference
2309 				assert( (g->next->prv_in_room != NULL) || (room_gems[g->next->room] == g->next) );
2310 
2311 				if (g->next == room_gems[g->next->room]) {
2312 					room_gems[g->next->room] = g->next->next_in_room;
2313 					if (room_gems[g->next->room] != NULL) {
2314 						room_gems[g->next->room]->prv_in_room = NULL;
2315 					}
2316 				} else {
2317 					g->next->prv_in_room->next_in_room = g->next->next_in_room;
2318 					if (g->next->next_in_room != NULL) {
2319 						g->next->next_in_room->prv_in_room = g->next->prv_in_room;
2320 					}
2321 				}
2322 				g_del = g->next;
2323 
2324 				g->next = g->next->next;
2325 				free(g_del);
2326 			}
2327 		}
2328 		g = g->next;
2329 	}
2330 
2331 	// delete old monsters
2332 	t = active_stack;
2333 	if (t != NULL) {
2334 		while (t->delete_me) {
2335 			t = t->next_active;
2336 			active_stack = t;
2337 
2338 			if (t == NULL) break;
2339 		}
2340 	}
2341 	while (t != NULL) {
2342 		if (t == active_stack)
2343 			assert(t->delete_me == 0);
2344 		else
2345 			assert(!t->delete_me);
2346 
2347 		if (t->next_active != NULL) {
2348 			while (t->next_active->delete_me) {
2349 				t->next_active = t->next_active->next_active;
2350 				if (t->next_active == NULL) break;
2351 			}
2352 		}
2353 		t = t->next_active;
2354 	}
2355 }
2356 
HurtEnemies(int x,int y,int range,int power)2357 void HurtEnemies(int x, int y, int range, int power)
2358 {
2359 	struct enemy *t;
2360 	int e_range;
2361 
2362 	t = active_stack;
2363 	while (t != NULL) {
2364 		e_range = sqrt(sqr(t->x - x) + sqr(t->y - y));
2365 		if (e_range < range) {
2366 			if (power >= t->str) {
2367 				if (t->room == GetRoom(x/32, y/32)) {
2368 					KillEnemy(t);
2369 				}
2370 			}
2371 		}
2372 		t = t->next_active;
2373 	}
2374 }
2375 
CircuitBullets(int x,int y,int r)2376 void CircuitBullets(int x, int y, int r)
2377 {
2378 	struct bullet *b;
2379 	b = bullet_stack;
2380 	while (b != NULL) {
2381 		if (!b->delete_me) {
2382 			if (b->dying == 0) {
2383 				if (b->invuln == 0) {
2384 					if (sqrt(sqr(b->x - x) + sqr(b->y - y)) < r) {
2385 						b->dying = 1;
2386 					}
2387 				}
2388 			}
2389 		}
2390 		b = b->next;
2391 	}
2392 }
2393 
CrystalSummon()2394 void CrystalSummon()
2395 {
2396 	struct diamond *g;
2397 	int rg_x, rg_y;
2398 	int i;
2399 
2400 	g = gem_stack;
2401 
2402 	for (i = 0; i < 3000; i++) {
2403 		room_gems[i] = NULL;
2404 	}
2405 
2406 	while (g != NULL) {
2407 		if (!g->delete_me) {
2408 			if (rooms[g->room].room_type != 3) {
2409 				g->room = player_room;
2410 				rg_x = rooms[player_room].x * 32 + 32 + rand()%(rooms[player_room].w*32-64);
2411 				rg_y = rooms[player_room].y * 32 + 32 + rand()%(rooms[player_room].h*32-64);
2412 				if (player_room == 0) {
2413 					rg_x = (rooms[player_room].x+5) * 32 + 32 + rand()%(8*32);
2414 					rg_y = (rooms[player_room].y+5) * 32 + 32 + rand()%(5*32);
2415 				}
2416 				while (IsSolid(Get(rg_x/32, rg_y/32))) {
2417 					rg_x = rooms[player_room].x * 32 + 32 + rand()%(rooms[player_room].w*32-64);
2418 					rg_y = rooms[player_room].y * 32 + 32 + rand()%(rooms[player_room].h*32-64);
2419 					if (player_room == 0) {
2420 						rg_x = (rooms[player_room].x+5) * 32 + 32 + rand()%(8*32);
2421 						rg_y = (rooms[player_room].y+5) * 32 + 32 + rand()%(5*32);
2422 					}
2423 				}
2424 				g->x = rg_x;
2425 				g->y = rg_y;
2426 			}
2427 		}
2428 		g->next_in_room = room_gems[g->room];
2429 		g->prv_in_room = NULL;
2430 		if (room_gems[g->room] != NULL) {
2431 			room_gems[g->room]->prv_in_room = g;
2432 		}
2433 		room_gems[g->room] = g;
2434 
2435 		g = g->next;
2436 	}
2437 }
2438 
ActivateRand()2439 void ActivateRand()
2440 {
2441 	struct enemy *e;
2442 	struct enemy *en[20000];
2443 	int ent = 0;
2444 
2445 	e = enemy_stack;
2446 
2447 	while (e != NULL) {
2448 		if (e->delete_me == 0) {
2449 			if (e->active == 0) {
2450 				en[ent++] = e;
2451 			}
2452 		}
2453 		e = e->next;
2454 	}
2455 	if (ent > 0) {
2456 		e = en[rand()%ent];
2457 
2458 		XActivateSingleEnemy(e);
2459 	}
2460 }
2461 
ClearBossBullets()2462 void ClearBossBullets()
2463 {
2464 	struct bullet *b = bullet_stack;
2465 	while (b != NULL) {
2466 		if (!b->delete_me) {
2467 			if (b->firer == NULL) {
2468 				b->delete_me = 1;
2469 			}
2470 		}
2471 		b = b->next;
2472 	}
2473 }
2474 
SpawnBullet(int x,int y,int bullet_type,float dir,float spd,int invuln)2475 void SpawnBullet(int x, int y, int bullet_type, float dir, float spd, int invuln)
2476 {
2477 	struct bullet *b;
2478 
2479 	if ( (current_boss == 3) && (player_shield == 30) && (boss_fight_mode == 2) ) {
2480 		spd *= 1.2;
2481 	}
2482 	b = CreateBullet(x, y, NULL, bullet_type, dir, spd);
2483 	if (invuln) {
2484 		b->invuln = 1;
2485 	}
2486 }
SpawnLaser(int x,int y,float dir,int fire_time,int duration,float turn,int dmg)2487 void SpawnLaser(int x, int y, float dir, int fire_time, int duration, float turn, int dmg)
2488 {
2489 	FireLaser(x, y, NULL, dir, fire_time, duration, turn, dmg);
2490 }
2491 
CullEnemies(int nth)2492 void CullEnemies(int nth)
2493 {
2494 	struct enemy *e;
2495 	int i = 0;
2496 
2497 	e = enemy_stack;
2498 
2499 	while (e != NULL) {
2500 		if (e->delete_me == 0) {
2501 			if (rooms[e->room].room_type == 0) {
2502 				if ( (i % nth) == (nth - 1)) {
2503 					e->delete_me = 1;
2504 					killed_enemies++;
2505 					e->dying = 0;
2506 					rooms[e->room].enemies--;
2507 				}
2508 				i++;
2509 			}
2510 		}
2511 		e = e->next;
2512 	}
2513 }
2514 
SoupUpEnemies()2515 void SoupUpEnemies()
2516 {
2517 	struct enemy *e;
2518 	int str_limit;
2519 	float str_multiplier;
2520 	float fr_divider;
2521 
2522 	e = enemy_stack;
2523 	str_limit = 1500;
2524 	if (circuit_size > 1500) {
2525 		str_limit = 1500;
2526 	}
2527 
2528 	str_multiplier = 1.0 + (1.0/3.0)*(float)current_boss;
2529 	fr_divider = 1.0 + (2.0/3.0)*(float)current_boss;
2530 
2531 	while (e != NULL) {
2532 		if (e->delete_me == 0) {
2533 			if (e->enemy_type != 10) {
2534 				if (e->str < str_limit) {
2535 					if ((e->str * 2) < str_limit) {
2536 						e->str = e->str * str_multiplier;
2537 					} else {
2538 						e->str = str_limit;
2539 					}
2540 				}
2541 				e->fire_rate = (int)((float)e->fire_rate / fr_divider) + 1;
2542 				e->speed = (int)((float)e->speed / fr_divider) + 1;
2543 				e->min_gems *= str_multiplier;
2544 				e->max_gems *= str_multiplier;
2545 			}
2546 		}
2547 		e = e->next;
2548 	}
2549 }
2550 
CurseSingleEnemy(struct enemy * e)2551 void CurseSingleEnemy(struct enemy *e)
2552 {
2553 	static int ActiveRooms[3000];
2554 	static int NActiveRooms = 0;
2555 	int i;
2556 	int rm;
2557 
2558 	if (NActiveRooms == 0) {
2559 		for (i = 0; i < 3000; i++) {
2560 			if ((rooms[i].room_type == 0) || (rooms[i].room_type == 4)) {
2561 				ActiveRooms[NActiveRooms++] = i;
2562 			}
2563 		}
2564 	}
2565 
2566 	rm = ActiveRooms[rand()%NActiveRooms];
2567 	while ((rooms[rm].enemies > 3) || (rooms[rm].visited == 0)) {
2568 		rm = ActiveRooms[rand()%NActiveRooms];
2569 	}
2570 
2571 	e->x = rooms[rm].w * 16 + rooms[rm].x * 32;
2572 	e->y = rooms[rm].h * 16 + rooms[rm].y * 32;
2573 	rooms[e->room].enemies--;
2574 	e->room = rm;
2575 	rooms[e->room].enemies++;
2576 
2577 	e->image = enemy_sprites[9];
2578 	e->lives = 8;
2579 	e->str = 500;
2580 	e->speed = 1;
2581 	e->fire_rate = (rand()%4)+1;
2582 	e->min_gems = 5000;
2583 	e->max_gems = 6000;
2584 	e->followdepth = 12;
2585 	e->creationcost = 6;
2586 	e->enemy_type = 10;
2587 
2588 	ActivateSingleEnemy(e);
2589 }
2590 
CurseEnemies()2591 void CurseEnemies()
2592 {
2593 	struct enemy *e;
2594 	int i = 0;
2595 
2596 	e = enemy_stack;
2597 
2598 	while (e != NULL) {
2599 		if (e->delete_me == 0) {
2600 			if ( (i % 5) == (4)) {
2601 				CurseSingleEnemy(e);
2602 			} else {
2603 				e->delete_me = 1;
2604 				killed_enemies++;
2605 
2606 				e->dying = 0;
2607 				rooms[e->room].enemies--;
2608 			}
2609 			i++;
2610 		}
2611 		e = e->next;
2612 	}
2613 }
2614