1 /*
2  * file player.c - ingame player mangment
3  *
4  * $Id: player.c,v 1.48 2006/06/13 11:11:27 fzago Exp $
5  *
6  * Program XBLAST
7  * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published
11  * by the Free Software Foundation; either version 2; or (at your option)
12  * any later version
13  *
14  * This program is distributed in the hope that it will be entertaining,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17  * Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.
21  * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "xblast.h"
25 
26 /*
27  * local constants
28  */
29 #define BOMB_STEP 2
30 #define STEP_HORI BASE_X
31 #define STEP_VERT BASE_Y
32 
33 #define MAX_RANGE 10
34 #define ILLTIME 256
35 #define ILL_X (4*BASE_X)
36 #define ILL_Y (5*BASE_Y)
37 
38 #define JUNKIE_ILL_TIME (ILLTIME)
39 #define JUNKIE_STUN_TIME 12
40 #define JUNKIE_TIME_1 360
41 #define JUNKIE_TIME_2 210
42 #define JUNKIE_TIME_3 60		/* Speed */
43 
44 #define NUM_TELE_TRIES 25
45 
46 /*
47  * init flags for extras
48  *   LF_ level start flag
49  *   RF_ revive flag
50  *   IF_ both of the above
51  */
52 #define IF_None     0
53 /* kick extra */
54 #define LF_Kick     (1<<29)
55 #define RF_Kick     (1<<30)
56 #define IF_Kick     (RF_Kick|LF_Kick)
57 /* remote control */
58 #define LF_RC       1
59 #define RF_RC       2
60 //#define IF_RC       3
61 /* teleporter */
62 #define LF_Teleport 4
63 #define RF_Teleport 5
64 //#define IF_Teleport 6
65 /* airpump */
66 #define LF_Airpump  7
67 #define RF_Airpump  8
68 //#define IF_Airpump  9
69 /* cloak extra */
70 #define LF_Cloak    10
71 #define RF_Cloak    11
72 //#define IF_Cloak    12
73 /* morph extra */
74 #define LF_Morph    13
75 #define RF_Morph    14
76 //#define IF_Morph    15
77 /** Skywalker **/
78 #define LF_Snipe    16
79 #define RF_Snipe    17
80 //#define IF_Snipe    18
81 #define LF_Frogger  19
82 #define RF_Frogger  20
83 //#define IF_Frogger  21
84 #define LF_Fart    22
85 #define RF_Fart    23
86 //#define IF_Fart    24
87 #define LF_Bfart   25
88 #define RF_Bfart   26
89 //#define IF_Bfart   27
90 #define LF_Choice  28
91 #define RF_Choice  29
92 //#define IF_Choice  30
93 #define LF_Stop    31
94 #define RF_Stop    32
95 //#define IF_Stop    33
96 #define LF_Phantom 34
97 #define RF_Phantom 35
98 //#define IF_Phantom 36
99 #define LF_Electrify 37
100 #define RF_Electrify 38
101 //#define IF_Electrify 39
102 
103 #define LF_Daleif    40
104 #define RF_Daleif    41
105 //#define IF_Daleif    42
106 #define LF_Suck  43
107 #define RF_Suck  44
108 //#define IF_Suck  45
109 
110 /* revive extra */
111 #define LF_Revive    46
112 #define RF_Revive   47
113 //#define IF_Revive    (RF_Revive|LF_Revive)
114 #define LF_Jump    48
115 #define RF_Jump   49
116 //#define IF_Revive    (RF_Revive|LF_Revive)
117 
118 #define LF_Reverse2    50
119 #define RF_Reverse2   51
120 #define LF_Through    52
121 #define RF_Through   53
122 /** **/
123 #define NUM_IF 12
124 
125 /*
126  * global variables
127  */
128 BMPlayer player_stat[2 * MAX_PLAYER];
129 PlayerStrings p_string[2 * MAX_PLAYER];
130 
131 /*
132  * extern variables
133  */
134 extern void (*special_extra_function) (void);
135 
136 /*
137  * local variables - retrieved from level data
138  */
139 static int minRange;
140 static int minBombs;
141 static int recLives;
142 static int specialBombs;
143 static int reviveHealth;
144 static int initHealth;
145 static unsigned initFlags;
146 static unsigned revFlags;
147 static BMPosition pos0[MAX_PLAYER];
148 static int pos0Shuffle[MAX_PLAYER];
149 static int pos0Cnt;
150 static int playersAllowed;
151 
152 /*
153  * local variables - defined by game data
154  */
155 static XBBool randomPlayerPos;
156 static XBBool ifRecLives;
157 static int maxLives;
158 static int numPlayer;
159 
160 /*
161  * local variables - for final setup
162  */
163 static BMPosition pos[MAX_PLAYER];
164 static unsigned iniplayerflags;
165 static unsigned revplayerflags;
166 
167 #if 0
168 static int game_mode;
169 #endif
170 
171 /* conversion tables */
172 static DBToInt healthTable[] = {
173 	{"bomb", (int)IllBomb},
174 	{"empty", (int)IllEmpty},
175 	{"healthy", (int)Healthy},
176 	{"invisible", (int)IllInvisible},
177 	{"malfunction", (int)IllMalfunction},
178 	{"mini", (int)IllMini},
179 	{"reverse", (int)IllReverse},
180 	{"reverse2", (int)IllReverse2},
181 	{"run", (int)IllRun},
182 	{"slow", (int)IllSlow},
183 	{"teleport", (int)IllTeleport},
184 	{NULL, -1},
185 };
186 static DBToInt initFlagsTable[] = {
187 	{"airpump", LF_Airpump},
188 	{"bfarter", LF_Bfart},
189 	{"choicebombtype", LF_Choice},	/* skywalker */
190 	{"cloak", LF_Cloak},
191 	{"daleif", LF_Daleif},
192 	{"electrify", LF_Electrify},
193 	{"farter", LF_Fart},		/* skywalker */
194 	{"frogger", LF_Frogger},	/* skywalker */
195 	{"jump", LF_Jump},			/* skywalker */
196 	{"kick", LF_Kick},
197 	{"morph", LF_Morph},
198 	{"none", 0},
199 	{"phantom", LF_Phantom},
200 	{"rc", LF_RC},
201 	{"revive", LF_Revive},
202 	{"snipe", LF_Snipe},			/** Skywalker **/
203 	{"stop", LF_Stop},
204 	{"sucker", LF_Suck},
205 	{"teleport", LF_Teleport},
206 	{"through", LF_Through},
207 	{NULL, -1},
208 };
209 static DBToInt reviveFlagsTable[] = {
210 	{"airpump", RF_Airpump},
211 	{"bfarter", RF_Bfart},
212 	{"choicebombtype", RF_Choice},	/* skywalker */
213 	{"cloak", RF_Cloak},
214 	{"daleif", RF_Daleif},
215 	{"electrify", RF_Electrify},
216 	{"farter", RF_Fart},		/* skywalker */
217 	{"frogger", RF_Frogger},	/* skywalker */
218 	{"jump", RF_Jump},			/* skywalker */
219 	{"kick", RF_Kick},
220 	{"morph", RF_Morph},
221 	{"none", 0},
222 	{"phantom", RF_Phantom},
223 	{"rc", RF_RC},
224 	{"revive", RF_Revive},
225 	{"snipe", RF_Snipe},		   /** Skywalker **/
226 	{"stop", RF_Stop},
227 	{"sucker", RF_Suck},
228 	{"teleport", RF_Teleport},
229 	{"through", RF_Through},
230 	{NULL, -1},
231 };
232 
233 /* info text data */
234 static const char *permHealthInfo[MAX_ILL] = {
235 	NULL,
236 	N_("Permanent random bombing"),
237 	N_("Permanent slowdown"),
238 	N_("Permanent running"),
239 	N_("Permanent mini bombs"),
240 	N_("No bomb while healthy"),
241 	N_("Permanent invisibility"),
242 	N_("Permanent malfunctions"),
243 	N_("Permanent reverse controls"),
244 	N_("Permanent reverse(2) controls"),
245 	N_("Permanent random teleporting"),
246 };
247 static const char *initHealthInfo[MAX_ILL] = {
248 	NULL,
249 	N_("Initial random bombing"),
250 	N_("Initial slowdown"),
251 	N_("Initial running"),
252 	N_("Initial mini bombs"),
253 	N_("No bomb while healthy"),
254 	N_("Initial invisibility"),
255 	N_("Initial malfunctions"),
256 	N_("Initial reverse controls"),
257 	N_("Initial reverse(2) controls"),
258 	N_("Initial random teleporting"),
259 };
260 static const char *reviveHealthInfo[MAX_ILL] = {
261 	NULL,
262 	N_("Revived with random bombing"),
263 	N_("Revived with slowdown"),
264 	N_("Revived with running"),
265 	N_("Revived with mini bombs"),
266 	N_("Revived with bombs while healthy"),
267 	N_("Revived with invisibility"),
268 	N_("Revived with malfunctions"),
269 	N_("Revived with reverse controls"),
270 	N_("Revived with reverse(2) controls"),
271 	N_("Revived with random teleporting"),
272 };
273 
274 /*
275  * parse player section in level data
276  */
277 XBBool
ParseLevelPlayers(const DBSection * section,unsigned gameMode,DBSection * warn)278 ParseLevelPlayers (const DBSection * section, unsigned gameMode, DBSection * warn)
279 {
280 	int i, k;
281 	/* check existence of section */
282 	if (NULL == section) {
283 		Dbg_Out ("LEVEL: player section is missing!\n");
284 		DB_CreateEntryString (warn, atomMissing, "true");
285 		return XBFalse;
286 	}
287 	/* Bombs entry is required */
288 	if (!DB_GetEntryInt (section, atomBombs, &minBombs)) {
289 		Dbg_Out ("LEVEL: critical failure, %s\n", DB_SectionEntryString (section, atomBombs));
290 		DB_CreateEntryString (warn, atomBombs, "missing!");
291 		return XBFalse;
292 	}
293 	/* Range entry is required */
294 	if (!DB_GetEntryInt (section, atomRange, &minRange)) {
295 		Dbg_Out ("LEVEL:  critical failure, %s\n", DB_SectionEntryString (section, atomRange));
296 		DB_CreateEntryString (warn, atomRange, "missing!");
297 		return XBFalse;
298 	}
299 	/* RecLives has default */
300 	if (!DB_GetEntryInt (section, atomRecLives, &recLives)) {
301 		Dbg_Level ("default for %s\n", DB_SectionEntryString (section, atomRecLives));
302 		recLives = 0;
303 	}
304 	/* SpecialBombs has default */
305 	if (!DB_GetEntryInt (section, atomSpecialBombs, &specialBombs)) {
306 		Dbg_Level ("default for %s\n", DB_SectionEntryString (section, atomSpecialBombs));
307 		specialBombs = 0;
308 	}
309 	/* ReviveVirus has default */
310 	switch (DB_ConvertEntryInt (section, atomReviveVirus, (int *)&reviveHealth, healthTable)) {
311 	case DCR_NoSuchEntry:
312 		Dbg_Level ("default for %s\n", DB_SectionEntryString (section, atomReviveVirus));
313 		reviveHealth = Healthy;
314 		break;
315 	case DCR_Failure:
316 		Dbg_Out ("LEVEL: warning for %s\n", DB_SectionEntryString (section, atomReviveVirus));
317 		reviveHealth = Healthy;
318 		DB_CreateEntryString (warn, atomReviveVirus, DB_IntToString (healthTable, reviveHealth));
319 		break;
320 	default:
321 		break;
322 	}
323 	/* InitVirus has default */
324 	switch (DB_ConvertEntryInt (section, atomInitVirus, (int *)&initHealth, healthTable)) {
325 	case DCR_NoSuchEntry:
326 		Dbg_Level ("default for %s\n", DB_SectionEntryString (section, atomInitVirus));
327 		initHealth = Healthy;
328 		break;
329 	case DCR_Failure:
330 		Dbg_Out ("LEVEL: warning %s\n", DB_SectionEntryString (section, atomInitVirus));
331 		initHealth = Healthy;
332 		DB_CreateEntryString (warn, atomInitVirus, DB_IntToString (healthTable, initHealth));
333 		break;
334 	default:
335 		break;
336 	}
337 	/* InitExtra has default */
338 	switch (DB_ConvertEntryFlags (section, atomInitExtra, &initFlags, initFlagsTable)) {
339 	case DCR_NoSuchEntry:
340 		Dbg_Level ("default for %s\n", DB_SectionEntryString (section, atomInitExtra));
341 		initFlags = 0;
342 		break;
343 	case DCR_Failure:
344 		Dbg_Out ("LEVEL: warning for %s\n", DB_SectionEntryString (section, atomInitExtra));
345 		initFlags = 0;
346 		DB_CreateEntryString (warn, atomInitExtra, DB_IntToString (initFlagsTable, initFlags));
347 		break;
348 	default:
349 		break;
350 	}
351 	/* ReviveExtra has default */
352 	switch (DB_ConvertEntryFlags (section, atomReviveExtra, &revFlags, reviveFlagsTable)) {
353 	case DCR_NoSuchEntry:
354 		Dbg_Level ("default for %s\n", DB_SectionEntryString (section, atomReviveExtra));
355 		revFlags = 0;
356 		break;
357 	case DCR_Failure:
358 		Dbg_Out ("LEVEL: warning for %s\n", DB_SectionEntryString (section, atomReviveExtra));
359 		revFlags = 0;
360 		DB_CreateEntryString (warn, atomReviveExtra, DB_IntToString (reviveFlagsTable, revFlags));
361 		break;
362 	default:
363 		break;
364 	}
365 	/* retrieve all player positions, count them */
366 	k = 0;
367 	for (i = 0; i < MAX_PLAYER; i++) {
368 		if (DB_GetEntryPos (section, atomArrayPos0[k + 1], pos0 + k)) {
369 			if ((pos0[k].x > 0) && (pos0[k].y > 0) &&
370 				(pos0[k].x <= MAZE_W) && (pos0[k].y <= MAZE_H)) {
371 				pos0Shuffle[k] = k;
372 				k++;
373 			}
374 		}
375 	}
376 	pos0Cnt = k;
377 	/* check if there are player positions */
378 	if (pos0Cnt == 0) {
379 		Dbg_Out ("LEVEL: critical failure, no player positions found!\n");
380 		DB_CreateEntryString (warn, atomArrayPos0[0], "missing!");
381 		return XBFalse;
382 	}
383 	Dbg_Level ("%u player positions found\n", pos0Cnt);
384 	/* retrieve number of allowed players from gameMode */
385 	k = 0;
386 	for (i = 5; (i > 0) && (k == 0); i--) {
387 		if ((gameMode & (1 << i)) != 0) {
388 			k = i + 1;
389 		}
390 	}
391 	playersAllowed = k;
392 	/* check if players are allowed at all */
393 	if (playersAllowed == 0) {
394 		Dbg_Out ("LEVEL: critical failure, no players allowed!\n");
395 		return XBFalse;
396 	}
397 	Dbg_Level ("%u players allowed\n", playersAllowed);
398 	return XBTrue;
399 }								/* ParseLevelPlayers */
400 
401 /*
402  * configure players for game
403  */
404 void
ConfigLevelPlayers(const DBSection * section,XBBool allowRandomPos,unsigned gameMode)405 ConfigLevelPlayers (const DBSection * section, XBBool allowRandomPos, unsigned gameMode)
406 {
407 	BMPlayer *ps;
408 	int i, j, k, m;
409 	int pl[MAX_PLAYER];
410 	int numActive;
411 	const char *s;
412 
413 	assert (section != NULL);
414 	revplayerflags = 0;
415 	iniplayerflags = 0;
416 
417 	/* min of allowed players and defined positions */
418 	k = MIN (pos0Cnt, playersAllowed);
419 	assert (k > 0);
420 	/* determine number of active players and shuffle list */
421 	numActive = 0;
422 	for (i = 0; i < numPlayer; i++) {
423 		if (!player_stat[i].in_active) {
424 			pl[numActive] = i;
425 			numActive++;
426 		}
427 	}
428 	Dbg_Level ("%u of %u players are active, %u defined positions - assigning positions...\n",
429 			   numActive, numPlayer, pos0Cnt);
430 	/* shuffle active players */
431 	for (i = numActive - 1; i > 0; i--) {
432 		j = GameRandomNumber (i + 1);
433 		j = (j >= 0) ? j : 0;
434 		j = (j >= i + 1) ? i : j;
435 		m = pl[j];
436 		pl[j] = pl[i];
437 		pl[i] = m;
438 	}
439 	/* shuffle retrieved positions */
440 	for (i = k - 1; i > 0; i--) {
441 		j = GameRandomNumber (i + 1);
442 		j = (j >= 0) ? j : 0;
443 		j = (j >= i + 1) ? i : j;
444 		m = pos0Shuffle[j];
445 		pos0Shuffle[j] = pos0Shuffle[i];
446 		pos0Shuffle[i] = m;
447 	}
448 	/* setup shuffled player positions */
449 	for (i = 0; i < numActive; i++) {
450 		if (i < k) {
451 			pos[pl[i]] = pos0[pos0Shuffle[i]];
452 			Dbg_Level ("active player %i on defined position %i (%i, %i)\n",
453 					   pl[i], pos0Shuffle[i], pos[pl[i]].x, pos[pl[i]].y);
454 		}
455 		else {
456 			j = GameRandomNumber (k);
457 			j = (j >= 0) ? j : 0;
458 			j = (j >= k) ? k - 1 : j;
459 			pos[pl[i]] = pos0[j];
460 			Dbg_Level ("active player %i on random position %i (%i, %i)\n",
461 					   pl[i], j, pos[pl[i]].x, pos[pl[i]].y);
462 
463 		}
464 	}
465 	/* store positions in player stats */
466 	j = 0;
467 	for (i = 0; i < numPlayer; i++) {
468 		ps = player_stat + i;
469 		if (ps->in_active) {
470 			ps->x = 0;
471 			ps->y = i * BLOCK_HEIGHT;
472 			SetSpriteMode (ps->sprite, SPM_UNMAPPED);
473 		}
474 		else {
475 			ps->x = pos[i].x * BLOCK_WIDTH;
476 			ps->y = (pos[i].y - 1) * BLOCK_HEIGHT;
477 
478 			j++;
479 		}
480 	}
481 	/* setup other player attributes */
482 	for (i = 0; i < numPlayer; i++) {
483 		ps = player_stat + i;
484 		/* Added by VVL (Chat) 12/11/99 : Begin */
485 		ps->chatmode = 0;
486 		ps->chatstring[0] = '\0';
487 		ps->chatlen = 0;
488 		/* Added by VVL (Chat) 12/11/99 : End */
489 		ps->iniextra_flags = initFlags;
490 		ps->revextra_flags = revFlags;
491 		iniplayerflags = (ps->iniextra_flags & ((0xffffff) >> 2));
492 		revplayerflags = (ps->revextra_flags & ((0xffffff) >> 2));
493 		ps->kick = (LF_Kick & ps->iniextra_flags) ? XBTrue : XBFalse;
494 		ps->invincible = NEW_INVINCIBLE;
495 		ps->illness = initHealth;
496 		ps->health = initHealth;
497 		ps->illtime = 0;
498 		ps->junkie = 0;
499 		ps->ghost = 0;
500 		ps->dying = 0;
501 		ps->stunned = 0;
502 		if (ifRecLives && recLives) {
503 			ps->lives = ps->in_active ? 0 : recLives;
504 		}
505 		else {
506 			ps->lives = ps->in_active ? 0 : maxLives;
507 		}
508 		ps->range = minRange;
509 		ps->bombs = minBombs;
510 		ps->special_bombs = specialBombs;
511 		ps->jump_button = (LF_Jump == iniplayerflags) ? XBTrue : XBFalse;
512 		ps->remote_control = (LF_RC == iniplayerflags) ? XBTrue : XBFalse;
513 		ps->teleport = (LF_Teleport == iniplayerflags) ? XBTrue : XBFalse;
514 		ps->air_button = (LF_Airpump == iniplayerflags) ? XBTrue : XBFalse;
515 		ps->cloaking = (LF_Cloak == iniplayerflags) ? -GAME_TIME : 0;
516 		ps->stop = (LF_Stop == iniplayerflags) ? XBTrue : XBFalse;
517 		ps->phantom = (LF_Phantom == iniplayerflags) ? GAME_TIME : XBFalse;
518 		ps->electrify = (LF_Electrify == iniplayerflags) ? EXTRA_ELECTRIFY_COUNT : XBFalse;
519 		ps->revive = (LF_Revive == iniplayerflags) ? XBTrue : XBFalse;
520 		ps->suck_button = (LF_Suck == iniplayerflags) ? XBTrue : XBFalse;
521 		ps->num_extras =
522 			(LF_Snipe == iniplayerflags) ? 1000 : ((LF_Morph == iniplayerflags) ? 1000 : 0);
523 		ps->speed = 0;
524 		ps->daleif = (LF_Daleif == iniplayerflags) ? XBTrue : XBFalse;	/* Daleif illness (galatius) */
525 		ps->farted = (LF_Fart == iniplayerflags) ? XBTrue : XBFalse;	/* Fart counter (galatius) */
526 		ps->bfarter = (LF_Bfart == iniplayerflags) ? XBTrue : XBFalse;	/* Fart counter (galatius) */
527 		ps->num_snipe = (LF_Snipe == iniplayerflags) ? 1000 : 0;
528 		ps->num_morph = (LF_Morph == iniplayerflags) ? 1000 : 0;
529 		ps->daleifing = 0;
530 		ps->abort = ABORT_NONE;
531 		ps->d_ist = GoStop;
532 		ps->d_soll = GoStop;
533 		ps->d_look = GoDown;
534 		ps->morphed = XBFalse;
535 		/* Written by VVL */
536 		ps->through = (LF_Through == iniplayerflags) ? XBTrue : XBFalse;
537 		ps->throughCount = ps->through ? 255 : 0;
538 		ps->evilill = 0;
539 	/** Skywalker **/
540 		ps->sniping = 0;
541 		ps->frogger = (LF_Frogger == iniplayerflags) ? XBTrue : XBFalse;
542 	/** **/
543 		if (LF_Choice == iniplayerflags) {
544 			char tutu[40];
545 			int h;
546 			for (h = ChoiceDefaultBomb; bomb_name_choice[h] == NULL; h = ((h + 1) % NUM_BMT)) ;
547 
548 			ps->choice_bomb_type = h;
549 			if (ps->local) {
550 				sprintf (tutu, "%s : ", p_string[ps->id].name);
551 				strcat (tutu, bomb_name_choice[(ps->choice_bomb_type)]);
552 				SetMessage (tutu, XBTrue);
553 			}
554 		}
555 		else {
556 			ps->choice_bomb_type = NUM_BMT;
557 			/* fprintf(stderr," bomb typ1 %i\n", ps->choice_bomb_type); */
558 		}
559 	}
560 	/* set text for info screen */
561 	switch (minBombs) {
562 	case 0:
563 		AddPlayerInfo (N_("No bomb"));
564 		break;
565 	case 1:
566 		AddPlayerInfo (N_("1 bomb"));
567 		break;
568 	default:
569                 /* TRANSLATORS: %d > 1 (multiple bombs only) */
570 		AddPlayerInfo (N_("%d bombs"), minBombs);
571 		break;
572 	}
573 	switch (minRange) {
574 	case 0:
575 		AddPlayerInfo (N_("No initial range"));
576 		break;
577 	case 1:
578 		AddPlayerInfo (N_("Only mini bombs"));
579 		break;
580 	default:
581 		AddPlayerInfo (N_("Initial range %d"), minRange);
582 		break;
583 	}
584 	if (initHealth == reviveHealth) {
585 		if (NULL != (s = permHealthInfo[initHealth])) {
586 			AddPlayerInfo (s);
587 		}
588 	}
589 	else {
590 		if (NULL != (s = initHealthInfo[initHealth])) {
591 			AddPlayerInfo (s);
592 		}
593 		if (NULL != (s = reviveHealthInfo[reviveHealth])) {
594 			AddPlayerInfo (s);
595 		}
596 	}
597 	if (iniplayerflags == LF_Daleif) {
598 		if (revplayerflags == RF_Daleif) {
599 			AddPlayerInfo (N_("Daleif as default"));
600 		}
601 		else {
602 			AddPlayerInfo (N_("Initial Daleif"));
603 		}
604 	}
605 	else if ((revplayerflags == RF_Daleif)) {
606 		AddPlayerInfo (N_("Revived with Daleif"));
607 	}
608 	if (iniplayerflags == LF_RC) {
609 		if (revplayerflags == RF_RC) {
610 			AddPlayerInfo (N_("Remote control as default"));
611 		}
612 		else {
613 			AddPlayerInfo (N_("Initial remote control"));
614 		}
615 	}
616 	else if ((revplayerflags == RF_RC)) {
617 		AddPlayerInfo (N_("Revived with remote control"));
618 	}
619 	if (iniplayerflags == LF_Jump) {
620 		if (revplayerflags == RF_Jump) {
621 			AddPlayerInfo (N_("Jump as default"));
622 		}
623 		else {
624 			AddPlayerInfo (N_("Initial Jump"));
625 		}
626 	}
627 	else if ((revplayerflags == RF_Jump)) {
628 		AddPlayerInfo (N_("Revived with Jump"));
629 	}
630 	if (iniplayerflags == LF_Airpump) {
631 		if (revplayerflags == RF_Airpump) {
632 			AddPlayerInfo (N_("Airpump as default"));
633 		}
634 		else {
635 			AddPlayerInfo (N_("Initial airpump"));
636 		}
637 	}
638 	else if (revplayerflags == RF_Airpump) {
639 		AddPlayerInfo (N_("Revived with airpump"));
640 	}
641 	if (iniplayerflags == LF_Cloak) {
642 		if (revplayerflags == RF_Cloak) {
643 			AddPlayerInfo (N_("Cloak as default"));
644 		}
645 		else {
646 			AddPlayerInfo (N_("Initial cloak"));
647 		}
648 	}
649 	else if (revplayerflags == RF_Cloak) {
650 		AddPlayerInfo (N_("Revived with cloak"));
651 	}
652 	if (iniplayerflags & LF_Kick) {
653 		if (revplayerflags == RF_Kick) {
654 			AddPlayerInfo (N_("Initial kick"));
655 		}
656 		else {
657 			AddPlayerInfo (N_("Initial kick"));
658 		}
659 	}
660 	else if (revplayerflags == RF_Kick) {
661 		AddPlayerInfo (N_("Revived with kick"));
662 	}
663 	if (iniplayerflags == LF_Morph) {
664 		if (revplayerflags == RF_Morph) {
665 			AddPlayerInfo (N_("Morphing as default"));
666 		}
667 		else {
668 			AddPlayerInfo (N_("Initial morphing"));
669 		}
670 	}
671 	else if (revplayerflags == RF_Morph) {
672 		AddPlayerInfo (N_("Revived with morphing"));
673 	}
674 	if (iniplayerflags == LF_Through) {
675 		if (revplayerflags == RF_Through) {
676 			AddPlayerInfo (N_("Throughing as default"));
677 		}
678 		else {
679 			AddPlayerInfo (N_("Initial throughing"));
680 		}
681 	}
682 	else if (revplayerflags == RF_Through) {
683 		AddPlayerInfo (N_("Revived with throughing"));
684 	}
685 
686 	if (iniplayerflags == LF_Suck) {
687 		if (revplayerflags == RF_Suck) {
688 			AddPlayerInfo (N_("Sucker as default"));
689 		}
690 		else {
691 			AddPlayerInfo (N_("Initial sucker"));
692 		}
693 	}
694 	else if (revplayerflags == RF_Suck) {
695 		AddPlayerInfo (N_("Revived with sucker"));
696 	}
697 	/* that's all folks */
698 }								/* ConfigLevelPlayers */
699 
700 /*
701  * Create Welcome messages for players at start of level
702  */
703 void
WelcomePlayers(void)704 WelcomePlayers (void)
705 {
706 	int i, j, num;
707 	const char *list[MAX_PLAYER];
708 	const char *swap;
709 
710 	/* get messages */
711 	for (i = 0, num = 0; i < numPlayer; i++) {
712 		if (NULL != p_string[i].welcome && !player_stat[i].in_active) {
713 			list[num++] = p_string[i].welcome;
714 		}
715 	}
716 	/* shuffle them */
717 	for (i = 0; i < num; i++) {
718 		j = OtherRandomNumber (num);
719 		swap = list[i];
720 		list[i] = list[j];
721 		list[j] = swap;
722 	}
723 	/* show them */
724 	for (i = 0; i < num; i++) {
725 		SetMessage (list[i], XBFalse);
726 	}
727 }								/* WelcomePlayers */
728 
729 /*
730  *
731  */
732 int
NumSpecialBombs(void)733 NumSpecialBombs (void)
734 {
735 	return specialBombs;
736 }								/* NumSpecialBombs */
737 
738 /*
739  * set player stat to default values
740  */
741 static void
InitPlayerStat(BMPlayer * ps,int player,int ctrl,XBPlayerTeam team,int PID,XBBool local)742 InitPlayerStat (BMPlayer * ps, int player, int ctrl, XBPlayerTeam team, int PID, XBBool local)	// XBCC
743 {
744 	/* set default values */
745 	ps->victories = 0;
746 	ps->PID = PID;				// XBCC
747 	ps->id = player;
748 	ps->disp = local ? SPM_MAPPED : SPM_UNMAPPED;
749 	ps->local = local;
750 	ps->sprite = CreatePlayerSprite (ps->id, 0, 0, 0, SPM_UNMAPPED);
751 	Dbg_Out (" sprite player %i %i", ((ps->sprite)->player).player, ps->id);
752 	((ps->sprite)->player).player = ps->id;
753 	Dbg_Out (" new sprite player %i %i\n", ((ps->sprite)->player).player, ps->id);
754 	ps->in_active = XBFalse;
755 	/* evaluate team mode */
756 	if (team == XBPT_None) {
757 		ps->team = ps->id;
758 	}
759 	else {
760 		ps->team = team - XBPT_None - 1;
761 	}
762 }								/* InitPlayerStat */
763 
764 /*
765  * set all messages for given player
766  */
767 static void
InitPlayerMessages(PlayerStrings * str,const CFGPlayer * cfgPlayer)768 InitPlayerMessages (PlayerStrings * str, const CFGPlayer * cfgPlayer)
769 {
770 	char tmp[128];
771 
772 	/* player name */
773 	str->name = DupString (cfgPlayer->name);
774 	assert (NULL != str->name);
775 	str->tag = DupString (cfgPlayer->name);
776 	assert (NULL != str->tag);
777 	/* pause string */
778 	sprintf (tmp, "Game paused by %s", str->name);
779 	str->pause = DupString (tmp);
780 	assert (NULL != str->pause);
781 	/* win a level */
782 	if (NULL != cfgPlayer->messages.msgWinLevel) {
783 		str->winlevel = DupString (cfgPlayer->messages.msgWinLevel);
784 	}
785 	else {
786 		sprintf (tmp, _("%s wins"), str->name);
787 		str->winlevel = DupString (tmp);
788 	}
789 	assert (NULL != str->winlevel);
790 	/* win the game */
791 	if (NULL != cfgPlayer->messages.msgWinGame) {
792 		str->wingame = DupString (cfgPlayer->messages.msgWinGame);
793 	}
794 	else {
795 		str->wingame = DupString (N_("CONGRATULATIONS!"));
796 	}
797 	assert (NULL != str->wingame);
798 	/* request abort */
799 	sprintf (tmp, "Abort requested by %s", str->tag);
800 	str->abort = DupString (tmp);
801 	assert (NULL != str->abort);
802 	/* cancel abort */
803 	sprintf (tmp, "%s cancels abort", str->tag);
804 	str->abortcancel = DupString (tmp);
805 	assert (str->abortcancel != NULL);
806 	/* loosing a life */
807 	if (NULL != cfgPlayer->messages.msgLoseLife) {
808 		str->loselife = DupString (cfgPlayer->messages.msgLoseLife);
809 	}
810 	else {
811 		str->loselife = NULL;
812 	}
813 	/* loosing a level */
814 	if (NULL != cfgPlayer->messages.msgLoseLevel) {
815 		str->loselevel = DupString (cfgPlayer->messages.msgLoseLevel);
816 	}
817 	else {
818 		str->loselevel = NULL;
819 	}
820 	/* gloating */
821 	if (NULL != cfgPlayer->messages.msgGloat) {
822 		str->gloat = DupString (cfgPlayer->messages.msgGloat);
823 	}
824 	else {
825 		str->gloat = NULL;
826 	}
827 	/* laola */
828 	if (NULL != cfgPlayer->messages.msgLaola) {
829 		str->laola = DupString (cfgPlayer->messages.msgLaola);
830 	}
831 	else {
832 		str->laola = NULL;
833 	}
834 	/* looser */
835 	if (NULL != cfgPlayer->messages.msgLoser) {
836 		str->loser = DupString (cfgPlayer->messages.msgLoser);
837 	}
838 	else {
839 		str->loser = NULL;
840 	}
841 	/* welcome to the game */
842 	if (NULL != cfgPlayer->messages.msgWelcome) {
843 		str->welcome = DupString (cfgPlayer->messages.msgWelcome);
844 	}
845 	else {
846 		str->welcome = NULL;
847 	}
848 }								/* InitPlayerMessages */
849 
850 /*
851  *
852  */
853 void
InitPlayers(XBPlayerHost host,const CFGGame * cfgGame,const CFGPlayer * cfgPlayer)854 InitPlayers (XBPlayerHost host, const CFGGame * cfgGame, const CFGPlayer * cfgPlayer)
855 {
856 	int i, j, cnt;
857 	XBBool local;
858 	BMPlayer *ps;
859 
860 	assert (NULL != cfgGame);
861 	assert (NULL != cfgPlayer);
862 
863 	/* global settings */
864 	numPlayer = cfgGame->players.num;
865 	maxLives = cfgGame->setup.numLives;
866 	ifRecLives = cfgGame->setup.ifRecLives;
867 	randomPlayerPos = cfgGame->setup.randomPlayers;
868 	cnt = 0;
869 	/* player settings */
870 	for (ps = player_stat, i = 0; i < cfgGame->players.num; ps++, i++) {
871 		assert (ATOM_INVALID != cfgGame->players.player[i]);
872 		local = (host == cfgGame->players.host[i]);
873 		if (local) {
874 			ps->localDisplay = cnt;
875 			cnt++;
876 			ps->bot = cfgGame->setup.bot;
877 		}
878 		else {
879 			ps->localDisplay = -1;
880 			ps->bot = XBFalse;
881 			if (XBPT_None != cfgGame->players.team[i]) {
882 				for (j = 0; j < cfgGame->players.num; j++) {
883 
884 					if (i != j && host == cfgGame->players.host[j]) {
885 						local = local || (cfgGame->players.team[i] == cfgGame->players.team[j]);
886 					}
887 				}
888 			}
889 		}
890 		ps->away = XBTrue;
891 		InitPlayerStat (player_stat + i, i, i, cfgGame->players.team[i], (cfgPlayer + i)->id.PID, local);	// XBCC
892 		InitPlayerMessages (p_string + i, cfgPlayer + i);
893 	}
894 }								/* InitPlayers */
895 
896 /*
897  *
898  */
899 void
FinishPlayers(void)900 FinishPlayers (void)
901 {
902 	int i;
903 	PlayerStrings *str;
904 
905 	for (i = 0; i < numPlayer; i++) {
906 		str = p_string + i;
907 		if (NULL != str->name) {
908 			free (str->name);
909 		}
910 		if (NULL != str->tag) {
911 			free (str->tag);
912 		}
913 		if (NULL != str->pause) {
914 			free (str->pause);
915 		}
916 		if (NULL != str->winlevel) {
917 			free (str->winlevel);
918 		}
919 		if (NULL != str->wingame) {
920 			free (str->wingame);
921 		}
922 		if (NULL != str->loselife) {
923 			free (str->loselife);
924 		}
925 		if (NULL != str->loselevel) {
926 			free (str->loselevel);
927 		}
928 		if (NULL != str->gloat) {
929 			free (str->gloat);
930 		}
931 		if (NULL != str->laola) {
932 			free (str->laola);
933 		}
934 		if (NULL != str->loser) {
935 			free (str->loser);
936 		}
937 		if (NULL != str->welcome) {
938 			free (str->welcome);
939 		}
940 		if (NULL != str->abort) {
941 			free (str->abort);
942 		}
943 		if (NULL != str->abortcancel) {
944 			free (str->abortcancel);
945 		}
946 	}
947 	numPlayer = 0;
948 }								/* FinishPlayers */
949 
950 /*
951  *
952  */
953 void
DeletePlayerSprites(void)954 DeletePlayerSprites (void)
955 {
956 	int player;
957 
958 	for (player = 0; player < numPlayer; player++) {
959 		DeleteSprite (player_stat[player].sprite);
960 	}
961 }								/* DeletePlayerSprites */
962 
963 /*
964  *
965  */
966 void
DropBomb(BMPlayer * ps,int type)967 DropBomb (BMPlayer * ps, int type)
968 {
969 	if ((ps->bombs != 0) && (ps->sniping != 1) &&	/* skywalker / koen */
970 		(ps->illness != IllEmpty) &&
971 		(ps->morphed < 2) &&
972 		(type == BMTdefault || ps->special_bombs > 0 || ps->choice_bomb_type != NUM_BMT)) {
973 		if (ps->lives > 0) {
974 			if (ps->choice_bomb_type != NUM_BMT)
975 				type = ps->choice_bomb_type;
976 			if (NewPlayerBomb (ps, type)) {
977 				SND_Play (SND_DROP, ps->x / (PIXW / MAX_SOUND_POSITION));
978 				ps->bombs--;
979 				if (ps->morphed) {
980 					ps->morphed = 2;
981 					ps->num_morph--;
982 				}
983 	/** Skywalker **/
984 				if (ps->sniping) {
985 					ps->num_snipe--;
986 				}
987 	/** **/
988 				if (type != BMTdefault && ps->choice_bomb_type == NUM_BMT) {
989 					ps->special_bombs--;
990 				}
991 			}
992 			else {
993 				if (ps->morphed) {
994 					ps->morphed = 0;
995 				}
996 			}
997 		}
998 	}
999 }								/* DropBomb */
1000 
1001 /*
1002  *
1003  */
1004 static void
WalkStop(BMPlayer * ps,int flag,int mazex,int mazey)1005 WalkStop (BMPlayer * ps, int flag, int mazex, int mazey)
1006 {
1007 	if (ps->illness != IllReverse) {
1008 		if (ps->illness == IllReverse2) {
1009 			switch (ps->d_look) {
1010 			case GoDown:
1011 				SetSpriteAnime (ps->sprite, SpriteStopLeft);
1012 				break;
1013 			case GoUp:
1014 				SetSpriteAnime (ps->sprite, SpriteStopRight);
1015 				break;
1016 			case GoLeft:
1017 				SetSpriteAnime (ps->sprite, SpriteStopDown);
1018 				break;
1019 			case GoRight:
1020 				SetSpriteAnime (ps->sprite, SpriteStopUp);
1021 				break;
1022 			default:
1023 				break;
1024 			}
1025 		}
1026 		else {
1027 			switch (ps->d_look) {
1028 			case GoDown:
1029 				SetSpriteAnime (ps->sprite, SpriteStopDown);
1030 				break;
1031 			case GoUp:
1032 				SetSpriteAnime (ps->sprite, SpriteStopUp);
1033 				break;
1034 			case GoLeft:
1035 				SetSpriteAnime (ps->sprite, SpriteStopLeft);
1036 				break;
1037 			case GoRight:
1038 				SetSpriteAnime (ps->sprite, SpriteStopRight);
1039 				break;
1040 			default:
1041 				break;
1042 			}
1043 		}
1044 	}
1045 	else {
1046 		switch (ps->d_look) {
1047 		case GoDown:
1048 			SetSpriteAnime (ps->sprite, SpriteStopUp);
1049 			break;
1050 		case GoUp:
1051 			SetSpriteAnime (ps->sprite, SpriteStopDown);
1052 			break;
1053 		case GoLeft:
1054 			SetSpriteAnime (ps->sprite, SpriteStopRight);
1055 			break;
1056 		case GoRight:
1057 			SetSpriteAnime (ps->sprite, SpriteStopLeft);
1058 			break;
1059 		default:
1060 			break;
1061 		}
1062 	}
1063 }								/* WalkStop */
1064 
1065 /*
1066  *
1067  */
1068 static void
WalkUp(BMPlayer * ps,int flag,int mazex,int mazey)1069 WalkUp (BMPlayer * ps, int flag, int mazex, int mazey)
1070 {
1071 	if (!(flag && CheckMazeGhost (ps->ghost, mazex, mazey - 1))
1072 		||
1073 		(!((ps->phantom) ? CheckMazePhantomWall (mazex, mazey - 1) : CheckMaze (mazex, mazey - 1))
1074 		 && (mazey > 1))) {
1075 		ps->y -= STEP_VERT;
1076 		if (ps->y < 0)
1077 			ps->y = PIXH - BLOCK_HEIGHT * 2;	// 02-05-2002
1078 		mazey = ps->y / BLOCK_HEIGHT + 1;
1079 		if (ps->illness != IllReverse) {
1080 			if (ps->illness == IllReverse2) {
1081 				SetSpriteAnime (ps->sprite, SpriteWalkLeft0 + ((ps->y / STEP_VERT) % 4));
1082 			}
1083 			else {
1084 				SetSpriteAnime (ps->sprite, SpriteWalkUp0 + ((ps->y / STEP_VERT) % 4));
1085 			}
1086 		}
1087 		else {
1088 			SetSpriteAnime (ps->sprite, SpriteWalkDown0 + ((ps->y / STEP_VERT) % 4));
1089 		}
1090 	}
1091 	else {
1092 		ps->d_ist = GoStop;
1093 		if (ps->illness != IllReverse) {
1094 			if (ps->illness == IllReverse2) {
1095 				SetSpriteAnime (ps->sprite, SpriteStopLeft);
1096 			}
1097 			else {
1098 				SetSpriteAnime (ps->sprite, SpriteStopUp);
1099 			}
1100 		}
1101 		else {
1102 			SetSpriteAnime (ps->sprite, SpriteStopDown);
1103 		}
1104 	}
1105 
1106 	/* try a kick */
1107 	if (CheckBomb (mazex, mazey)
1108 		&& ((ps->y % BLOCK_HEIGHT) == (STEP_VERT * BOMB_STEP) && (!ps->through)) && (!ps->through)) {
1109 		if (ps->kick) {
1110 			SND_Play (SND_KICK, ps->x / (PIXW / MAX_SOUND_POSITION));
1111 			/* added by Galatius */
1112 			switch (ps->daleif & GameRandomNumber (2)) {
1113 			case 0:
1114 				MoveBomb (mazex, mazey, GoUp);
1115 				break;
1116 			case 1:
1117 				ps->daleifing = DALEIF_TIME;
1118 				MoveBomb (mazex, mazey, GoDown);
1119 				break;
1120 			}					/* end added by Galatius */
1121 			ps->d_soll = GoStop;
1122 		}
1123 		ps->y += STEP_VERT;
1124 		ps->y = (ps->y + PIXH) % PIXH;
1125 	}
1126 	//   if(oldy!=ps->y)SND_Play (SND_STEP4, ps->x / (PIXW / MAX_SOUND_POSITION));
1127 }								/* WalkUp */
1128 
1129 /*
1130  * local function walk_left
1131  */
1132 static void
WalkLeft(BMPlayer * ps,int flag,int mazex,int mazey)1133 WalkLeft (BMPlayer * ps, int flag, int mazex, int mazey)
1134 {
1135 	if (!(flag && CheckMazeGhost (ps->ghost, mazex - 1, mazey)) ||
1136 		(!((ps->phantom) ? CheckMazePhantomWall (mazex - 1, mazey) : CheckMaze (mazex - 1, mazey))
1137 		 && (mazex > 1))) {
1138 		ps->x -= STEP_HORI;
1139 		if (ps->x < 0)
1140 			ps->x = PIXW;		// 02-05-2002
1141 		mazex = ps->x / BLOCK_WIDTH;
1142 		if (ps->illness != IllReverse) {
1143 			if (ps->illness == IllReverse2) {
1144 				SetSpriteAnime (ps->sprite, SpriteWalkDown0 + ((ps->x / STEP_VERT) % 4));
1145 			}
1146 			else {
1147 				SetSpriteAnime (ps->sprite, SpriteWalkLeft0 + ((ps->x / STEP_HORI) % 4));
1148 			}
1149 		}
1150 		else {
1151 			SetSpriteAnime (ps->sprite, SpriteWalkRight0 + ((ps->x / STEP_HORI) % 4));
1152 		}
1153 	}
1154 	else {
1155 		ps->d_ist = GoStop;
1156 		if (ps->illness != IllReverse) {
1157 			if (ps->illness == IllReverse2) {
1158 				SetSpriteAnime (ps->sprite, SpriteStopDown);
1159 			}
1160 			else {
1161 				SetSpriteAnime (ps->sprite, SpriteStopLeft);
1162 			}
1163 		}
1164 		else {
1165 			SetSpriteAnime (ps->sprite, SpriteStopRight);
1166 		}
1167 	}
1168 
1169 	/* try a kick */
1170 	if (CheckBomb (mazex, mazey)
1171 		&& ((ps->x % BLOCK_WIDTH) == (STEP_HORI * BOMB_STEP)) && (!ps->through)) {
1172 		if (ps->kick) {
1173 			SND_Play (SND_KICK, ps->x / (PIXW / MAX_SOUND_POSITION));
1174 			/* added by Galatius */
1175 			switch (ps->daleif & GameRandomNumber (2)) {
1176 			case 0:
1177 
1178 				MoveBomb (mazex, mazey, GoLeft);
1179 				break;
1180 			case 1:
1181 				ps->daleifing = DALEIF_TIME;
1182 				MoveBomb (mazex, mazey, GoRight);
1183 
1184 				break;
1185 			default:
1186 				break;
1187 
1188 			}
1189 			ps->d_soll = GoStop;
1190 			/* end added by Galatius */
1191 		}
1192 		ps->x += STEP_HORI;
1193 	}
1194 	//  if(oldx!=ps->x)SND_Play (SND_STEP1, ps->x / (PIXW / MAX_SOUND_POSITION));
1195 }								/* WalkLeft */
1196 
1197 /*
1198  *
1199  */
1200 static void
WalkDown(BMPlayer * ps,int flag,int mazex,int mazey)1201 WalkDown (BMPlayer * ps, int flag, int mazex, int mazey)
1202 {
1203 	if (!(flag && CheckMazeGhost (ps->ghost, mazex, mazey + 1)) ||
1204 		(!((ps->phantom) ? CheckMazePhantomWall (mazex, mazey + 1) : CheckMaze (mazex, mazey + 1))
1205 		 && (mazey < (MAZE_H - 2)))) {
1206 		ps->y += STEP_VERT;
1207 		if (ps->y >= (PIXH - BLOCK_HEIGHT * 2))
1208 			ps->y = 0;			// 02-05-2002
1209 
1210 		mazey = ps->y / BLOCK_HEIGHT + 1;
1211 		if (ps->illness != IllReverse) {
1212 			if (ps->illness == IllReverse2) {
1213 				SetSpriteAnime (ps->sprite, SpriteWalkRight0 + ((ps->y / STEP_VERT) % 4));
1214 			}
1215 			else {
1216 				SetSpriteAnime (ps->sprite, SpriteWalkDown0 + ((ps->y / STEP_VERT) % 4));
1217 			}
1218 		}
1219 		else {
1220 			SetSpriteAnime (ps->sprite, SpriteWalkUp0 + ((ps->y / STEP_VERT) % 4));
1221 		}
1222 	}
1223 	else {
1224 		ps->d_ist = GoStop;
1225 		if (ps->illness != IllReverse) {
1226 			if (ps->illness == IllReverse2) {
1227 				SetSpriteAnime (ps->sprite, SpriteStopRight);
1228 			}
1229 			else {
1230 				SetSpriteAnime (ps->sprite, SpriteStopDown);
1231 			}
1232 		}
1233 		else {
1234 			SetSpriteAnime (ps->sprite, SpriteStopUp);
1235 		}
1236 	}
1237 
1238 	/* try a kick */
1239 	if (CheckBomb (mazex, mazey + 1)
1240 		&& ((ps->y % BLOCK_HEIGHT) == (BLOCK_HEIGHT - STEP_VERT * BOMB_STEP))
1241 		&& (!ps->through)
1242 		) {
1243 		if (ps->kick) {
1244 			SND_Play (SND_KICK, ps->x / (PIXW / MAX_SOUND_POSITION));
1245 			/* added by Galatius */
1246 			switch (ps->daleif & GameRandomNumber (2)) {
1247 			case 0:
1248 				MoveBomb (mazex, mazey + 1, GoDown);
1249 				break;
1250 			case 1:
1251 				ps->daleifing = DALEIF_TIME;
1252 				MoveBomb (mazex, mazey + 1, GoUp);
1253 				break;
1254 			}
1255 			/* end added by Galatius */
1256 			ps->d_soll = GoStop;
1257 		}
1258 		ps->y -= STEP_VERT;
1259 	}
1260 	//if(oldy!=ps->y) SND_Play (SND_STEP2, ps->x / (PIXW / MAX_SOUND_POSITION));
1261 }								/* WalkDown */
1262 
1263 /*
1264  *
1265  */
1266 static void
WalkRight(BMPlayer * ps,int flag,int mazex,int mazey)1267 WalkRight (BMPlayer * ps, int flag, int mazex, int mazey)
1268 {
1269 	if (!(flag && CheckMazeGhost (ps->ghost, mazex + 1, mazey)) ||
1270 		(!((ps->phantom) ? CheckMazePhantomWall (mazex + 1, mazey) : CheckMaze (mazex + 1, mazey))
1271 		 && (mazex < (MAZE_W - 2)))) {
1272 		ps->x += STEP_HORI;
1273 		if (ps->x >= PIXW - BLOCK_WIDTH)
1274 			ps->x = 0;			// 02-05-2002
1275 		mazex = ps->x / BLOCK_WIDTH;
1276 		if (ps->illness != IllReverse) {
1277 			if (ps->illness == IllReverse2) {
1278 				SetSpriteAnime (ps->sprite, SpriteWalkUp0 + ((ps->x / STEP_VERT) % 4));
1279 			}
1280 			else {
1281 				SetSpriteAnime (ps->sprite, SpriteWalkRight0 + ((ps->x / STEP_HORI) % 4));
1282 			}
1283 		}
1284 		else {
1285 			SetSpriteAnime (ps->sprite, SpriteWalkLeft0 + ((ps->x / STEP_HORI) % 4));
1286 		}
1287 	}
1288 	else {
1289 		ps->d_ist = GoStop;
1290 		if (ps->illness != IllReverse) {
1291 			if (ps->illness == IllReverse2) {
1292 				SetSpriteAnime (ps->sprite, SpriteStopUp);
1293 			}
1294 			else {
1295 				SetSpriteAnime (ps->sprite, SpriteStopRight);
1296 			}
1297 		}
1298 		else {
1299 			SetSpriteAnime (ps->sprite, SpriteStopLeft);
1300 		}
1301 	}
1302 
1303 	/* try kick */
1304 	if (CheckBomb (mazex + 1, mazey)
1305 		&& ((ps->x % BLOCK_WIDTH) == (BLOCK_WIDTH - STEP_HORI * BOMB_STEP))
1306 		&& (!ps->through)) {
1307 		if (ps->kick) {
1308 			SND_Play (SND_KICK, ps->x / (PIXW / MAX_SOUND_POSITION));
1309 			/* added by Galatius */
1310 			switch (ps->daleif & GameRandomNumber (2)) {
1311 			case 0:
1312 				MoveBomb (mazex + 1, mazey, GoRight);
1313 				break;
1314 			case 1:
1315 				ps->daleifing = DALEIF_TIME;
1316 				MoveBomb (mazex + 1, mazey, GoLeft);
1317 				break;
1318 			}
1319 			/* end added by Galatius */
1320 			ps->d_soll = GoStop;
1321 		}
1322 		ps->x -= STEP_HORI;
1323 	}
1324 	//  if(oldx!=ps->x)SND_Play (SND_STEP3, ps->x / (PIXW / MAX_SOUND_POSITION));
1325 }								/* WalkRight */
1326 
1327 /*
1328  * try to teleport player
1329  */
1330 static XBBool
TeleportPlayer(BMPlayer * ps,int mazeX,int mazeY)1331 TeleportPlayer (BMPlayer * ps, int mazeX, int mazeY)
1332 {
1333 	int newMazeX, newMazeY;
1334 	int i, j, n;
1335 	int fs[MAZE_W * MAZE_H];
1336 
1337 	n = 0;
1338 	for (i = 0; i < MAZE_W; i++) {
1339 		for (j = 0; j < MAZE_H; j++) {
1340 			if (!CheckMaze (i, j)) {
1341 				fs[n] = i + j * MAZE_W;
1342 				n++;
1343 			}
1344 		}
1345 	}
1346 
1347 	if (n > 0) {
1348 		i = fs[GameRandomNumber (n)];
1349 		newMazeX = i % MAZE_W;
1350 		newMazeY = i / MAZE_W;
1351 		if (((ps->
1352 			  phantom) ? (!CheckMazePhantomWall (newMazeX, newMazeY)) : (!CheckMaze (newMazeX,
1353 																					 newMazeY)))
1354 			&& ((mazeX != newMazeX) || (mazeY != newMazeY))) {
1355 			SND_Play (SND_TELE1, ps->x / (PIXW / MAX_SOUND_POSITION));
1356 			ps->x = newMazeX * BLOCK_WIDTH;
1357 			ps->y = (newMazeY - 1) * BLOCK_HEIGHT;
1358 			ps->d_soll = GoStop;
1359 			ps->d_look = GoDown;
1360 			SND_Play (SND_TELE2, ps->x / (PIXW / MAX_SOUND_POSITION));
1361 			return XBTrue;
1362 		}
1363 	}
1364 
1365 	return XBFalse;
1366 }								/* TeleportPlayer */
1367 
1368 /*
1369  * local function do_walk
1370  */
1371 static void
DoWalk(BMPlayer * ps,int gameTime)1372 DoWalk (BMPlayer * ps, int gameTime)
1373 {
1374 	XBBool flag;
1375 	int mazeX, mazeY;
1376 	int i;
1377 	int xalt, yalt;
1378 	int spm_mode;
1379 
1380 	xalt = ps->x;
1381 	yalt = ps->y;
1382 
1383 	if (ps->illness != IllSlow || 0 == gameTime % 2) {
1384 		for (i = 0; i <= (ps->illness == IllRun) * ((ps->speed == 0) ? 1 : ps->speed); i++) {
1385 			flag = XBFalse;
1386 			mazeX = ps->x / BLOCK_WIDTH;
1387 			mazeY = ps->y / BLOCK_HEIGHT + 1;
1388 
1389 			if (0 == (ps->x % BLOCK_WIDTH) && 0 == (ps->y % BLOCK_HEIGHT)) {
1390 				flag = XBTrue;
1391 				/* check if player has deliberately teleported */
1392 				if (ps->teleport == TELEPORT_TIME) {
1393 					if (TeleportPlayer (ps, mazeX, mazeY)) {
1394 						ps->teleport--;
1395 					}
1396 				}
1397 				/* change direction if needed */
1398 				ps->d_ist = ps->d_soll;
1399 				if (ps->d_ist != GoStop) {
1400 					ps->d_look = ps->d_ist;
1401 				}
1402 			}
1403 			/* random teleporting */
1404 			if ((ps->illness == IllTeleport) && (0 == GameRandomNumber (32))) {
1405 				TeleportPlayer (ps, mazeX, mazeY);
1406 				ps->d_ist = GoStop;
1407 				ps->d_soll = GoStop;
1408 			}
1409 			/* let the player walk */
1410 			if (ps->sniping != 1) {	/* skywalker / koen */
1411 				switch (ps->d_ist) {
1412 				case GoStop:
1413 					WalkStop (ps, flag, mazeX, mazeY);
1414 					break;
1415 				case GoLeft:
1416 					WalkLeft (ps, flag, mazeX, mazeY);
1417 					break;
1418 				case GoRight:
1419 					WalkRight (ps, flag, mazeX, mazeY);
1420 					break;
1421 				case GoDown:
1422 					WalkDown (ps, flag, mazeX, mazeY);
1423 					break;
1424 				case GoUp:
1425 					WalkUp (ps, flag, mazeX, mazeY);
1426 					break;
1427 				default:
1428 					break;
1429 				}
1430 			}
1431 			MoveSprite (ps->sprite, ps->x, ps->y);
1432 
1433 			/* insert get _extra here */
1434 			if ((ps->x % BLOCK_WIDTH == 0) && (ps->y % BLOCK_HEIGHT == 0)) {
1435 				switch (GetExtra (ps->invincible, ps->x / BLOCK_WIDTH, ps->y / BLOCK_HEIGHT + 1)) {
1436 				case BTBomb:
1437 					SND_Play (SND_NEWBOMB, ps->x / (PIXW / MAX_SOUND_POSITION));
1438 					ps->bombs++;
1439 					break;
1440 				case BTRange:
1441 					SND_Play (SND_MOREFIRE, ps->x / (PIXW / MAX_SOUND_POSITION));
1442 					if (ps->range < MAX_RANGE) {
1443 						ps->range++;
1444 					}
1445 					break;
1446 				case BTSick:
1447 					ps->illtime = ILLTIME;
1448 					ps->illness = GameRandomNumber (MAX_ILL) + 1;
1449 					if (ps->illness == IllInvisible) {
1450 						SND_Play (SND_INVIS, ps->x / (PIXW / MAX_SOUND_POSITION));
1451 					}
1452 					else {
1453 						SND_Play (SND_BAD, ps->x / (PIXW / MAX_SOUND_POSITION));
1454 					}
1455 					if (ps->illness == IllReverse) {
1456 						switch (ps->d_ist) {
1457 						case GoDown:
1458 							ps->d_ist = GoUp;
1459 							break;
1460 						case GoUp:
1461 							ps->d_ist = GoDown;
1462 							break;
1463 						case GoLeft:
1464 							ps->d_ist = GoRight;
1465 							break;
1466 						case GoRight:
1467 							ps->d_ist = GoLeft;
1468 							break;
1469 						default:
1470 							break;
1471 						}
1472 					}
1473 					if (ps->illness == IllReverse2) {
1474 						switch (ps->d_ist) {
1475 						case GoDown:
1476 							ps->d_ist = GoLeft;
1477 							break;
1478 						case GoUp:
1479 							ps->d_ist = GoRight;
1480 							break;
1481 						case GoLeft:
1482 							ps->d_ist = GoUp;
1483 							break;
1484 						case GoRight:
1485 							ps->d_ist = GoDown;
1486 							break;
1487 						default:
1488 							break;
1489 						}
1490 					}
1491 					break;
1492 
1493 				case BTSpecial:
1494 					ps->num_extras++;
1495 					(*specialExtraFunc) (ps);
1496 					break;
1497 				}
1498 			}
1499 		}
1500 	}							/*decrement phantom time */
1501 	/* Written by Amilhastre */
1502 	if (ps->phantom > 0) {
1503 		ps->phantom--;
1504 	}
1505 /* Added by "Belgium Guys" */
1506 	if (ps->through) {
1507 		ps->through--;
1508 	}
1509 	if (ps->ghost) {
1510 		ps->ghost--;
1511 /* Written by VVL */
1512 		if ((ps->ghost == 0) && (ps->lives > 0)) {
1513 			if (CheckMaze ((ps->x / BLOCK_WIDTH), (ps->y / BLOCK_HEIGHT) + 1)) {
1514 				ps->lives = 1;
1515 				ps->dying = DEAD_TIME;
1516 			}
1517 		}
1518 	}
1519 	/* Skywalker */
1520 	if (ps->laola) {
1521 		static BMSpriteAnimation laola_animation[6] = {
1522 			SpriteWinner3, SpriteWinner2, SpriteWinner,
1523 			SpriteWinner, SpriteWinner2,
1524 			SpriteWinner3
1525 		};
1526 		SetSpriteAnime (ps->sprite, laola_animation[ps->laola - 1]);
1527 		ps->laola--;
1528 	}
1529 	else {
1530 		if (ps->looser) {
1531 			static BMSpriteAnimation looser_animation[10] = {
1532 				SpriteLooser, SpriteLooser, SpriteLooser1, SpriteLooser1, SpriteLooser,
1533 				SpriteLooser, SpriteLooser, SpriteLooser2, SpriteLooser2, SpriteLooser,
1534 			};
1535 			SetSpriteAnime (ps->sprite, looser_animation[ps->looser - 1]);
1536 			ps->looser--;
1537 		}
1538 	}
1539 	/* */
1540 	// 02-05-2002, reinco BUG fixed
1541 	if (ps->invincible > 0) {
1542 		ps->invincible--;
1543 	}
1544 	else if (ps->teleport > 1) {
1545 		ps->teleport--;
1546 	}
1547 
1548 	/* draw player if not totally invisible or morphed */
1549 	if (ps->in_active) {
1550 		spm_mode = SPM_UNMAPPED;
1551 	}
1552 	else if (ps->illness != IllInvisible) {
1553 		/* set default mode */
1554 		spm_mode = SPM_MAPPED;
1555 		/* first check for cloak */
1556 		if (ps->cloaking < 0) {
1557 			ps->cloaking++;
1558 			if (ps->cloaking & 0x01) {
1559 				spm_mode = ps->disp;
1560 			}
1561 			else {
1562 				spm_mode = SPM_UNMAPPED;
1563 			}
1564 		}
1565 		/* Added by "Belgium Guys" *//* blinking if gost_time < 64 */
1566 		if ((ps->ghost < 64) && (ps->ghost)) {
1567 			if (ps->ghost & 0x01) {
1568 				spm_mode |= SPM_MASKED;
1569 			}
1570 		}
1571 
1572 		/* blinking if invincible */
1573 		if (ps->invincible > 0) {
1574 			if (ps->invincible & 0x01) {
1575 				spm_mode |= SPM_MASKED;
1576 			}
1577 			/* or slower blinking if arrived from teleport */
1578 		}
1579 		else if (ps->teleport > 1) {
1580 			if ((ps->teleport >> 1) & 0x01) {
1581 				spm_mode |= SPM_MASKED;
1582 			}
1583 		}
1584 	}
1585 	else {
1586 		spm_mode = SPM_UNMAPPED;
1587 	}
1588 	SetSpriteMode (ps->sprite, spm_mode);
1589 
1590 	/* is player still sick? */
1591 	if (ps->illness != ps->health) {
1592 		/* decrement illness timer */
1593 		if ((ps->illtime--) == 0) {
1594 			/* heal if time is over */
1595 			ps->illness = ps->health;
1596 		}
1597 	}
1598 
1599 	/* drop random bombs if needed */
1600 	if ((ps->x % BLOCK_WIDTH == 0) && (ps->y % BLOCK_HEIGHT == 0)) {
1601 		if (ps->illness == IllBomb) {
1602 			if (GameRandomNumber (4) != 0) {
1603 				if (ps->choice_bomb_type != NUM_BMT)
1604 					DropBomb (ps, ps->choice_bomb_type);
1605 				else
1606 					DropBomb (ps, BMTdefault);
1607 
1608 			}
1609 		}
1610 	}
1611 }								/* DoWalk */
1612 
1613 /*
1614  *
1615  */
1616 static void
DoMorph(BMPlayer * ps)1617 DoMorph (BMPlayer * ps)
1618 {
1619 	SetSpriteAnime (ps->sprite, SpriteMorphed);
1620 	SetSpriteMode (ps->sprite, (ps->morphed == 2) ? SPM_MAPPED : SPM_UNMAPPED);
1621 	if (ps->d_soll != GoStop) {
1622 		MoveBomb (ps->x / BLOCK_WIDTH, ps->y / BLOCK_HEIGHT + 1, ps->d_soll);
1623 		ps->d_soll = GoStop;
1624 	}
1625 }								/* DoMorph */
1626 
1627 /*
1628  *
1629  */
1630 void
DoJunkie(void)1631 DoJunkie (void)
1632 {
1633 	BMPlayer *ps1;
1634 
1635 	/* Junkie countdown */
1636 	for (ps1 = player_stat; ps1 < player_stat + numPlayer; ps1++) {
1637 		if ((ps1->lives) && (ps1->junkie)) {
1638 			/* Junkie sickness */
1639 			switch (--(ps1->junkie)) {
1640 			case JUNKIE_TIME_1:
1641 			case JUNKIE_TIME_2:
1642 				/* Give a random illness */
1643 				ps1->illtime = JUNKIE_ILL_TIME;
1644 				ps1->illness = GameRandomNumber (MAX_ILL) + 1;
1645 				break;
1646 
1647 			case JUNKIE_TIME_3:
1648 				/* Stun player and give speed */
1649 				ps1->stunned += JUNKIE_STUN_TIME;
1650 				ps1->illtime = JUNKIE_ILL_TIME;
1651 				ps1->illness = IllRun;
1652 				break;
1653 
1654 			case 0:
1655 				/* Too long! Take a hit. */
1656 				ps1->dying = DEAD_TIME;
1657 				ps1->junkie = MAX_JUNKIE_TIME;
1658 				break;
1659 			}
1660 		}
1661 	}
1662 }								/* DoJunkie */
1663 
1664  /**/
1665 /* public function Electrify_other_players */
1666 	 /**/ int
ElectrifyOtherPlayers(int nplayer)1667 ElectrifyOtherPlayers (int nplayer)
1668 {
1669 	int player;
1670 	int count = 0;
1671 
1672 	for (player = 0; player < numPlayer; player++) {
1673 		if (nplayer != player) {
1674 			if (player_stat[player].lives) {
1675 				if ((ABS (player_stat[player].x - player_stat[nplayer].x) < (BLOCK_WIDTH * 3 / 4))
1676 					&& (ABS (player_stat[player].y - player_stat[nplayer].y) <
1677 						(BLOCK_HEIGHT * 3 / 4))) {
1678 					player_stat[player].dying = DEAD_TIME;
1679 					player_stat[player].electrify = 0;
1680 					count++;
1681 				}
1682 			}
1683 		}
1684 	}
1685 	return (count > 0);
1686 }
1687 
1688 /*
1689  *
1690  */
1691 void
InfectOtherPlayers(int * active_player)1692 InfectOtherPlayers (int *active_player)
1693 {
1694 	BMPlayer *ps1, *ps2;
1695 	BMPlayer *ptr;
1696 	int i, team_alive, equipe;
1697 
1698 	for (ps1 = player_stat; ps1 < player_stat + numPlayer; ps1++) {
1699 		for (ps2 = ps1 + 1; ps2 < player_stat + numPlayer; ps2++) {
1700 			if ((ABS (ps1->x - ps2->x) < ILL_X)
1701 				&& (ABS (ps1->y - ps2->y) < ILL_Y)) {
1702 				if (ps1->lives && ps2->lives) {
1703 					/* infection with "evil grail" virus */
1704 
1705 					if (ps1->evilill && (!ps2->invincible)) {
1706 						ps1->illtime = ps1->evilill = 0;
1707 						ps1->illness = ps1->health = IllRun;
1708 						ps1->kick = XBTrue;
1709 						ps1->invincible += BONUSEVIL;
1710 						ps1->phantom += BONUSEVIL;
1711 						if (ps1->cloaking > 0)
1712 							ps1->cloaking = -(ps1->cloaking + BONUSEVIL);
1713 						else
1714 							ps1->cloaking -= BONUSEVIL;
1715 						ps1->revive += 1;
1716 						ps2->evilill = ILLDEATHTIME;
1717 
1718 					}
1719 					else if (ps2->evilill && (!ps1->invincible)) {
1720 						ps2->illtime = ps2->evilill = 0;
1721 						ps2->illness = ps2->health = IllRun;
1722 						ps2->kick = XBTrue;
1723 						ps2->invincible += BONUSEVIL;
1724 						ps2->phantom += BONUSEVIL;
1725 						if (ps2->cloaking > 0)
1726 							ps2->cloaking = -(ps2->cloaking + BONUSEVIL);
1727 						else
1728 							ps2->cloaking -= BONUSEVIL;
1729 						ps2->revive += 1;
1730 						ps1->evilill = ILLDEATHTIME;
1731 					}
1732 					/* infection with "normal" viruses */
1733 					if (ps1->illness != ps2->illness) {
1734 						if ((!ps2->invincible) && (ps1->illtime > ps2->illtime)) {
1735 							ps2->illness = ps1->illness;
1736 							ps2->illtime = ILLTIME;
1737 						}
1738 						else if ((!ps1->invincible) && (ps2->illtime > ps1->illtime)) {
1739 							ps1->illness = ps2->illness;
1740 							ps1->illtime = ILLTIME;
1741 						}
1742 					}
1743 					/* infection with junkie virus */
1744 					if (((ps2->junkie) && (!ps1->invincible)) || (ps1->junkie)) {
1745 						ps1->junkie = MAX_JUNKIE_TIME;
1746 					}
1747 					if (((ps1->junkie) && (!ps2->invincible)) || (ps2->junkie)) {
1748 						ps2->junkie = MAX_JUNKIE_TIME;
1749 					}
1750 				}
1751 				else {
1752 					if ((ps2->lives) && (ps1->revive)) {
1753 						equipe = -1;
1754 						team_alive = XBFalse;
1755 						for (i = 0, ptr = player_stat; i < numPlayer; i++, ptr++) {
1756 							if (ptr->team == ps1->team) {
1757 								team_alive |= (ptr->lives != 0);
1758 								equipe++;
1759 							}
1760 						}
1761 
1762 						if (!team_alive)
1763 							(*active_player)++;
1764 						ps1->lives = 1;
1765 						ps1->revive--;
1766 					}
1767 
1768 					if ((ps1->lives) && (ps2->revive)) {
1769 						equipe = -1;
1770 						team_alive = XBFalse;
1771 						for (i = 0, ptr = player_stat; i < numPlayer; i++, ptr++) {
1772 							if (ptr->team == ps2->team) {
1773 								team_alive |= (ptr->lives != 0);
1774 								equipe++;
1775 							}
1776 						}
1777 
1778 						if (!team_alive)
1779 							(*active_player)++;
1780 						ps2->lives = 1;
1781 						ps2->revive--;
1782 
1783 					}
1784 				}
1785 			}
1786 		}
1787 	}
1788 }								/* InfectOtherPlayers */
1789 
1790 /*
1791  *
1792  */
1793 static void
HaveAGloat(int player)1794 HaveAGloat (int player)
1795 {
1796 	int g, gloatpl, gloatpltt;
1797 
1798 	gloatpl = -1;
1799 	for (g = 0; g < 6; g++) {
1800 		gloatpltt = OtherRandomNumber (numPlayer);
1801 		if (gloatpltt != player && player_stat[gloatpltt].lives > 0) {
1802 			gloatpl = gloatpltt;
1803 			break;
1804 		}
1805 	}
1806 	if (gloatpl > -1) {
1807 		SetMessage (p_string[gloatpl].gloat, XBFalse);
1808 	}
1809 }								/* HaveAGloat */
1810 
1811 void
SetMsgLaola(int player)1812 SetMsgLaola (int player)
1813 {
1814 	SetMessage (p_string[player].laola, XBFalse);
1815 
1816 }
1817 
1818 void
SetMsgLoser(int player)1819 SetMsgLoser (int player)
1820 {
1821 	SetMessage (p_string[player].loser, XBFalse);
1822 
1823 }
1824 
1825 																				 /* Added by Fouf on 09/02/99 22:46:25 *//* Added by "Belgium Guys" */ /**/
1826 	/* local function kill_player_at_ghost */
1827 	 /**/ void
KillPlayerAtGhost(int block,int x,int y)1828 KillPlayerAtGhost (int block, int x, int y)
1829 {
1830 	BMPlayer *ps;
1831 	int player;
1832 
1833 	for (player = 0; player < numPlayer; player++) {
1834 		ps = player_stat + player;
1835 		if (!ps->ghost || block == BTVoid) {
1836 			if (ps->lives > 0) {
1837 				if ((ps->x < (x + 1) * BLOCK_WIDTH)
1838 					&& (ps->x > (x - 1) * BLOCK_WIDTH)
1839 					&& (ps->y < (y) * BLOCK_HEIGHT)
1840 					&& (ps->y > (y - 2) * BLOCK_HEIGHT)) {
1841 					ps->lives = 1;
1842 					ps->dying = DEAD_TIME;
1843 				}
1844 			}
1845 		}
1846 	}
1847 }
1848 
1849 /*
1850  *
1851  */
1852 void
KillPlayerAt(int x,int y)1853 KillPlayerAt (int x, int y)
1854 {
1855 	BMPlayer *ps;
1856 	int player;
1857 
1858 	for (player = 0; player < numPlayer; player++) {
1859 		ps = player_stat + player;
1860 /* Added by "Belgium Guys" */
1861 		if (!ps->ghost) {
1862 			if (ps->lives > 0) {
1863 				if ((ps->x < (x + 1) * BLOCK_WIDTH)
1864 					&& (ps->x > (x - 1) * BLOCK_WIDTH)
1865 					&& (ps->y < (y) * BLOCK_HEIGHT)
1866 					&& (ps->y > (y - 2) * BLOCK_HEIGHT)) {
1867 					ps->lives = 1;
1868 					ps->dying = DEAD_TIME;
1869 				}
1870 			}
1871 		}
1872 	}
1873 }								/* KillPlayerAt */
1874 
1875 /*
1876  *
1877  */
1878 int
KillOtherPlayers(int team)1879 KillOtherPlayers (int team)
1880 {
1881 	int count = 0;
1882 	int player;
1883 
1884 	for (player = 0; player < numPlayer; player++) {
1885 		if ((player_stat[player].team != team)
1886 			&& (player_stat[player].lives > 0)) {
1887 			player_stat[player].dying = DEAD_TIME;
1888 			count++;
1889 		}
1890 	}
1891 
1892 	return count;
1893 }								/* KillOtherPlayers */
1894 
1895 /*
1896  *
1897  */
1898 int
StunOtherPlayers(int team,int time)1899 StunOtherPlayers (int team, int time)
1900 {
1901 	int count = 0;
1902 	int player;
1903 
1904 	for (player = 0; player < numPlayer; player++) {
1905 		if ((player_stat[player].team != team)
1906 			&& (!player_stat[player].invincible > 0)) {
1907 			SND_Play (SND_STUN, player_stat[player].x / (PIXW / MAX_SOUND_POSITION));
1908 			player_stat[player].stunned = time;
1909 			count++;
1910 		}
1911 	}
1912 	return count;
1913 }								/* StunOtherPlayers */
1914 
1915 /*Skywalker */
1916 
1917  /**/
1918 /* public function fart_on_other_players (galatius) */
1919 	 /**/ int
FartOnOtherPlayers(BMPlayer * ps)1920 FartOnOtherPlayers (BMPlayer * ps)
1921 {
1922 	BMPlayer *ps1;
1923 	int ex, ey;
1924 	int count = 0;
1925 
1926 	/*  do_bell(); */
1927 	if (ps->stunned || ps->smelly) {
1928 		return (count > 0);
1929 	}
1930 	ps->smelly = SMELLY_TIME;
1931 
1932 	for (ps1 = player_stat; ps1 < player_stat + numPlayer; ps1++) {
1933 		if ((ps1->lives == 0) || (ps1->invincible) ||
1934 			((ps->x == ps1->x) && (ps->y == ps1->y)) ||
1935 			(ABS (ps1->x - ps->x) >= (BLOCK_WIDTH * 2)) ||
1936 			(ABS (ps1->y - ps->y) >= (BLOCK_HEIGHT * 2))) {
1937 			continue;
1938 		}						/* Now ps will fart ps1 */
1939 
1940 		ps1->farted = 20;		/* Fart counter */
1941 
1942 		ex = (ps1->x - ps->x) * BLOCK_HEIGHT;
1943 		ey = (ps1->y - ps->y) * BLOCK_WIDTH;
1944 
1945 		switch (ps1->d_ist) {
1946 		case GoStop:
1947 			if (ABS (ex) >= ABS (ey)) {
1948 				ps1->d_soll = (ex < 0 ? GoLeft : GoRight);
1949 			}
1950 			else {
1951 				ps1->d_soll = (ey < 0 ? GoUp : GoDown);
1952 			}
1953 			break;
1954 		case GoRight:
1955 		case GoLeft:
1956 			ps1->d_soll = (ex < 0 ? GoLeft : GoRight);
1957 			break;
1958 		case GoUp:
1959 		case GoDown:
1960 			ps1->d_soll = (ey < 0 ? GoUp : GoDown);
1961 			break;
1962 		default:
1963 			break;
1964 		}
1965 
1966 		ps1->illness = IllRun;
1967 		ps1->illtime = 20;
1968 		ps1->stunned = 20;
1969 
1970 		count++;
1971 	}
1972 	return (count > 0);
1973 }
1974 
1975  /**/
1976 /* public function Swap_color_other_players */
1977 	 /**/ void
SwapColorOtherPlayers(int team)1978 SwapColorOtherPlayers (int team)
1979 {
1980 	int count = 0;
1981 	int D[MAX_PLAYER];
1982 	int RR;
1983 	int player;
1984 
1985 	if (numPlayer == 2) {
1986 		RR = ((player_stat[0].sprite)->player).player;
1987 		((player_stat[0].sprite)->player).player = ((player_stat[1].sprite)->player).player;
1988 		((player_stat[1].sprite)->player).player = RR;
1989 		MarkMazeSprite (player_stat[0].sprite);
1990 		MarkMazeSprite (player_stat[1].sprite);
1991 	}
1992 	else {
1993 
1994 		for (player = 0; player < numPlayer; player++) {
1995 			if (((player_stat[player].team) != team) && player_stat[player].lives) {
1996 				D[count] = player;
1997 				count++;
1998 			}
1999 		}
2000 
2001 		if (count > 2) {
2002 			RR = ((player_stat[D[0]].sprite)->player).player;
2003 			for (player = 0; player < count - 1; player++) {
2004 				((player_stat[D[player]].sprite)->player).player =
2005 					((player_stat[D[player + 1]].sprite)->player).player;
2006 				MarkMazeSprite (player_stat[D[player]].sprite);
2007 			}
2008 			((player_stat[D[count - 1]].sprite)->player).player = RR;
2009 			MarkMazeSprite (player_stat[D[count - 1]].sprite);
2010 		}
2011 		else {
2012 			if (count == 2) {
2013 				RR = ((player_stat[D[0]].sprite)->player).player;
2014 				((player_stat[D[0]].sprite)->player).player =
2015 					((player_stat[D[1]].sprite)->player).player;
2016 				((player_stat[D[1]].sprite)->player).player = RR;
2017 				MarkMazeSprite ((player_stat[D[0]].sprite));
2018 				MarkMazeSprite ((player_stat[D[1]].sprite));
2019 			}
2020 		}
2021 	}
2022 }
2023 
2024 #if unused
2025  /**/
2026 /* public function Swap_color_other_players2 */
2027 	 /**/ void
SwapColorOtherPlayers2(int team)2028 SwapColorOtherPlayers2 (int team)
2029 {
2030 	int count = 0;
2031 	int D[MAX_PLAYER];
2032 	int RR;
2033 	int player;
2034 	int swapper = 0;
2035 
2036 	fprintf (stderr, "count %i \n", count);
2037 	if (numPlayer == 2) {
2038 		RR = ((player_stat[0].sprite)->player).player;
2039 		((player_stat[0].sprite)->player).player = ((player_stat[1].sprite)->player).player;
2040 		((player_stat[1].sprite)->player).player = RR;
2041 		MarkMazeSprite (player_stat[0].sprite);
2042 		MarkMazeSprite (player_stat[1].sprite);
2043 	}
2044 	else {
2045 
2046 		for (player = 0; player < numPlayer; player++) {
2047 			if (player_stat[player].lives) {
2048 				if (((player_stat[player].team) != team)) {
2049 					D[count] = player;
2050 					count++;
2051 				}
2052 				else {
2053 					swapper = player;
2054 				}
2055 			}
2056 		}
2057 
2058 		if (count > 2) {
2059 			RR = ((player_stat[D[0]].sprite)->player).player;
2060 			for (player = 0; player < count - 1; player++) {
2061 				((player_stat[D[player]].sprite)->player).player =
2062 					((player_stat[D[player + 1]].sprite)->player).player;
2063 				MarkMazeSprite (player_stat[D[player]].sprite);
2064 			}
2065 			((player_stat[D[count - 1]].sprite)->player).player = RR;
2066 			MarkMazeSprite (player_stat[D[count - 1]].sprite);
2067 		}
2068 		/* 2 or 3 players, count 1 or 2 */
2069 		else {
2070 			if (count > 0) {
2071 				fprintf (stderr, "count %i numPlayer %i\n", count, numPlayer);
2072 				if (count == 1)
2073 					D[1] = swapper;
2074 
2075 				RR = ((player_stat[D[0]].sprite)->player).player;
2076 				((player_stat[D[0]].sprite)->player).player =
2077 					((player_stat[D[1]].sprite)->player).player;
2078 				((player_stat[D[1]].sprite)->player).player = RR;
2079 				MarkMazeSprite ((player_stat[D[0]].sprite));
2080 				MarkMazeSprite ((player_stat[D[1]].sprite));
2081 			}
2082 
2083 		}
2084 	}
2085 }
2086 #endif
2087 
2088 /*Skywalker */
2089 
2090  /**/
2091 /* public function steal_bombs_other_players */
2092 	 /**/ int
StealBombsOtherPlayers(int team)2093 StealBombsOtherPlayers (int team)
2094 {
2095 	int count = 0;
2096 	int player;
2097 
2098 	for (player = 0; player < numPlayer; player++) {
2099 		if (player_stat[player].team != team) {
2100 			if (player_stat[player].bombs > 0) {
2101 				player_stat[player].bombs--;
2102 				count++;
2103 			}
2104 		}
2105 	}
2106 	return count;
2107 }
2108 
2109  /**/
2110 /* public function steal_range_other_players */
2111 	 /**/ int
StealRangeOtherPlayers(int team)2112 StealRangeOtherPlayers (int team)
2113 {
2114 	int count = 0;
2115 	int player;
2116 	for (player = 0; player < numPlayer; player++) {
2117 		if (player_stat[player].team != team) {
2118 			if (player_stat[player].range > 1) {
2119 				player_stat[player].range--;
2120 				count++;
2121 			}
2122 		}
2123 	}
2124 	return count;
2125 }
2126 
2127  /**/
2128 /* public function Swap_position_other_players */
2129 	 /**/ void
SwapPositionOtherPlayers(int team)2130 SwapPositionOtherPlayers (int team)
2131 {
2132 	int x = 0, y = 0;
2133 	int first = -1;
2134 	int player;
2135 	int count = 0;
2136 
2137 	for (player = 0; player < numPlayer; player++) {
2138 		if ((player_stat[player].team) != team) {
2139 			count++;
2140 			if (player_stat[player].lives) {
2141 				if (first > -1) {
2142 					player_stat[first].x = (player_stat[player].x / BLOCK_WIDTH) * BLOCK_WIDTH;
2143 					player_stat[first].y = (player_stat[player].y / BLOCK_HEIGHT) * BLOCK_HEIGHT;
2144 					first = player;
2145 				}
2146 				else {
2147 					first = player;
2148 					x = (player_stat[player].x / BLOCK_WIDTH) * BLOCK_WIDTH;;
2149 					y = (player_stat[player].y / BLOCK_HEIGHT) * BLOCK_HEIGHT;;
2150 				}
2151 			}
2152 		}
2153 	}
2154 	if (count > 1) {
2155 		if (first > -1) {
2156 			player_stat[first].x = x;
2157 			player_stat[first].y = y;
2158 		}
2159 	}
2160 
2161 	if (numPlayer == 2) {
2162 		x = (player_stat[0].x / BLOCK_WIDTH) * BLOCK_WIDTH;
2163 		y = (player_stat[0].y / BLOCK_HEIGHT) * BLOCK_HEIGHT;
2164 		player_stat[0].x = (player_stat[1].x / BLOCK_WIDTH) * BLOCK_WIDTH;
2165 		player_stat[0].y = (player_stat[1].y / BLOCK_HEIGHT) * BLOCK_HEIGHT;
2166 		player_stat[1].x = x;
2167 		player_stat[1].y = y;
2168 	}
2169 }
2170 
2171 #ifdef unused
2172  /**/
2173 /* public function Swap_position_other_players2 */
2174 	 /**/ void
SwapPositionOtherPlayers2(int team)2175 SwapPositionOtherPlayers2 (int team)
2176 {
2177 	int x = 0, y = 0;
2178 	int first = -1;
2179 	int player, swapper = 0;
2180 	int count = 0;
2181 
2182 	for (player = 0; player < numPlayer; player++) {
2183 		if (player_stat[player].lives) {
2184 			if ((player_stat[player].team) != team) {
2185 				count++;
2186 				if (first > -1) {
2187 					player_stat[first].x = (player_stat[player].x / BLOCK_WIDTH) * BLOCK_WIDTH;
2188 					player_stat[first].y = (player_stat[player].y / BLOCK_HEIGHT) * BLOCK_HEIGHT;
2189 					first = player;
2190 				}
2191 				else {
2192 					first = player;
2193 					x = (player_stat[player].x / BLOCK_WIDTH) * BLOCK_WIDTH;;
2194 					y = (player_stat[player].y / BLOCK_HEIGHT) * BLOCK_HEIGHT;;
2195 				}
2196 			}
2197 			else {
2198 				swapper = player;
2199 			}
2200 		}
2201 	}
2202 	if (count > 1) {
2203 		if (first > -1) {
2204 			player_stat[first].x = x;
2205 			player_stat[first].y = y;
2206 		}
2207 	}
2208 	/* count==1 */
2209 	else {
2210 		if (first > -1) {
2211 			player_stat[first].x = (player_stat[swapper].x / BLOCK_WIDTH) * BLOCK_WIDTH;
2212 			player_stat[first].y = (player_stat[swapper].y / BLOCK_HEIGHT) * BLOCK_HEIGHT;
2213 			player_stat[swapper].x = x;
2214 			player_stat[swapper].y = y;
2215 		}
2216 	}
2217 
2218 	if (numPlayer == 2) {
2219 		x = (player_stat[0].x / BLOCK_WIDTH) * BLOCK_WIDTH;
2220 		y = (player_stat[0].y / BLOCK_HEIGHT) * BLOCK_HEIGHT;
2221 		player_stat[0].x = (player_stat[1].x / BLOCK_WIDTH) * BLOCK_WIDTH;
2222 		player_stat[0].y = (player_stat[1].y / BLOCK_HEIGHT) * BLOCK_HEIGHT;
2223 		player_stat[1].x = x;
2224 		player_stat[1].y = y;
2225 	}
2226 }
2227 #endif
2228 
2229 /* added by Skywalker */
2230  /**/
2231 /* public function do_frog (galatius) */
2232 	 /**/ void
DoFrog(BMPlayer * ps)2233 DoFrog (BMPlayer * ps)
2234 {
2235 	int ex, ey;
2236 	int frogs = ps->frogger;
2237 
2238 	if (!ps->d_ist == GoStop) {
2239 		/* If you are already moving: */
2240 		ex = ps->x % BLOCK_WIDTH;
2241 		ey = ps->y % BLOCK_HEIGHT;
2242 
2243 		switch (ps->d_ist) {
2244 		case GoDown:
2245 		case GoUp:
2246 			ps->y -= ey + ((ps->d_ist == GoUp) - 1) * BLOCK_HEIGHT;
2247 			break;
2248 		case GoRight:
2249 		case GoLeft:
2250 			ps->x -= ex + ((ps->d_ist == GoLeft) - 1) * BLOCK_WIDTH;
2251 			break;
2252 		default:
2253 			break;
2254 		}
2255 
2256 		frogs--;
2257 	}
2258 
2259 	ex = 0;
2260 	ey = 0;
2261 	switch (ps->d_look) {
2262 	case GoDown:
2263 		ey = 1;
2264 		break;
2265 	case GoUp:
2266 		ey = -1;
2267 		break;
2268 	case GoRight:
2269 		ex = 1;
2270 		break;
2271 	case GoLeft:
2272 		ex = -1;
2273 		break;
2274 	default:
2275 		break;
2276 	}
2277 
2278 	ps->x += ex * BLOCK_WIDTH * frogs;
2279 	ps->y += ey * BLOCK_HEIGHT * frogs;
2280 
2281 	ps->x = MAX (0, MIN (14 * BLOCK_WIDTH, ps->x));
2282 	ps->y = MAX (-BLOCK_HEIGHT, MIN (11 * BLOCK_HEIGHT, ps->y));
2283 
2284 	if (CheckMaze (ps->x / BLOCK_WIDTH, ps->y / BLOCK_HEIGHT + 1)) {
2285 		MoveSprite (ps->sprite, ps->x, ps->y);
2286 		ps->lives = 1;
2287 		ps->dying = DEAD_TIME;
2288 	}
2289 
2290 	ps->d_soll = GoStop;
2291 
2292 }
2293 
2294 /* end added by Skywalker */
2295 
2296 /*
2297  *
2298  */
2299 static void
RevivePlayer(BMPlayer * ps,int * active_player)2300 RevivePlayer (BMPlayer * ps, int *active_player)
2301 {
2302 	BMPlayer *ptr;
2303 	PlayerStrings *st;
2304 	int i, team_alive;
2305 	int playerflags;
2306 
2307 	st = p_string + ps->id;
2308 
2309 	ps->lives--;
2310 	/* check if player has lost all lives? */
2311 	if (ps->lives == 0) {
2312 		SetSpriteMode (ps->sprite, SPM_UNMAPPED);
2313 		SND_Play (SND_DEAD, ps->x / (PIXW / MAX_SOUND_POSITION));
2314 		team_alive = XBFalse;
2315 		for (i = 0, ptr = player_stat; i < numPlayer; i++, ptr++) {
2316 			if (ptr->team == ps->team) {
2317 				team_alive |= (ptr->lives != 0);
2318 			}
2319 		}
2320 		if (!team_alive) {
2321 			(*active_player)--;
2322 		}
2323 		DistributeExtras (ps->bombs - minBombs, ps->range - minRange, ps->num_extras,
2324 						  ps->special_bombs);
2325 		SetMessage (st->loselevel, XBFalse);
2326 	}
2327 	else {
2328 		SND_Play (SND_OUCH, ps->x / (PIXW / MAX_SOUND_POSITION));
2329 		DistributeExtras (0, 0, ps->num_extras, ps->special_bombs);
2330 		SetMessage (st->loselife, XBFalse);
2331 	}
2332 	HaveAGloat (ps->id);
2333 	/* reset values */
2334 	playerflags = (ps->revextra_flags & ((0xffffff) >> 2));
2335 	ps->invincible = NEW_INVINCIBLE;
2336 	ps->dying = 0;
2337 	ps->stunned = 0;
2338 	ps->illness = reviveHealth;
2339 	ps->health = reviveHealth;
2340 	ps->illtime = 0;
2341 	ps->teleport = 0;
2342 	ps->cloaking = XBFalse;
2343 	ps->morphed = XBFalse;
2344 	ps->num_morph = 0;
2345 	ps->evilill = 0;
2346 	ps->phantom = 0;
2347 	ps->through = 0;
2348 	ps->throughCount = 0;
2349 	ps->farted = (RF_Fart == playerflags) ? XBTrue : XBFalse;	/* (galatius) */
2350 	ps->smelly = 0;				/* (galatius) */
2351 	ps->bfarter = (RF_Bfart == playerflags) ? XBTrue : XBFalse;	/* (galatius) */
2352 	if (!ps->revive)
2353 		ps->cloaking = 0;
2354 
2355 	/* Note that junkie ISN'T reset (not a bug) */
2356 	/* very important */
2357 	if (ps->remote_control > 0) {
2358 		IgnitePlayersBombs (ps);
2359 	}
2360 	ps->daleifing = 0;			/* (galatius) */
2361 	ps->daleif = (RF_Daleif == playerflags) ? XBTrue : XBFalse;	/* (galatius) */
2362 
2363 	ps->remote_control = XBFalse;
2364 	ps->kick = XBFalse;
2365 	ps->air_button = XBFalse;
2366 	ps->frogger = (RF_Frogger == playerflags) ? XBTrue : XBFalse;	/*Skywalker */
2367 	ps->jump_button = (RF_Jump == playerflags) ? XBTrue : XBFalse;	/*Skywalker */
2368 	ps->evilill = 0;
2369 	ps->stop = (RF_Stop == playerflags) ? XBTrue : XBFalse;	/*Skywalker */
2370 	ps->suck_button = (RF_Suck == playerflags) ? XBTrue : XBFalse;	/*Skywalker */
2371 	ps->phantom = (RF_Phantom == playerflags) ? GAME_TIME : XBFalse;	/*Skywalker */
2372 	ps->electrify = (RF_Electrify == playerflags) ? EXTRA_ELECTRIFY_COUNT : XBFalse;	/*Skywalker */
2373 	/* If special bombs are distributed, then zero the count */
2374 	if (DistribSpecial ()) {
2375 		ps->special_bombs = 0;
2376 	}
2377 	/* Reset extra pickup count */
2378 	ps->num_extras = 0;
2379 	/* reset inital extras */
2380 	if (RF_RC == playerflags) {
2381 		ps->remote_control = 1;
2382 	}
2383 	if (RF_Teleport == playerflags) {
2384 		ps->teleport = 1;
2385 	}
2386 
2387 	if (RF_Kick & ps->revextra_flags) {
2388 		ps->kick = 1;
2389 	}
2390 	if (RF_Morph == playerflags) {
2391 		ps->num_morph = 1000;
2392 	}
2393 	if (RF_Through == playerflags) {
2394 		ps->through = XBTrue;
2395 		ps->throughCount = 255;
2396 	}
2397 	if (RF_Snipe == playerflags) {
2398 		ps->num_snipe = 1000;
2399 	}
2400 	ps->speed = 0;
2401 
2402 	if (RF_Revive == playerflags) {
2403 		ps->revive = 1;
2404 	}
2405 	ps->choice_bomb_type = NUM_BMT;
2406 	if (ps->local)
2407 		ResetMessage ();
2408 	if (RF_Choice == playerflags) {
2409 		int h;
2410 		for (h = ChoiceDefaultBomb; bomb_name_choice[h] == NULL; h = ((h + 1) % NUM_BMT)) ;
2411 		ps->choice_bomb_type = h;
2412 		if (ps->local && ps->lives) {
2413 			char tutu[40];
2414 			sprintf (tutu, "%s : ", p_string[ps->id].name);
2415 			strcat (tutu, bomb_name_choice[(ps->choice_bomb_type)]);
2416 			SetMessage (tutu, XBTrue);
2417 		}
2418 	}
2419 	if (RF_Airpump == playerflags) {
2420 		ps->air_button = 1;
2421 	}
2422 	if (RF_Cloak == playerflags) {
2423 		ps->cloaking = -GAME_TIME;
2424 	}
2425 	/* if revived ignite the bombs! */
2426 	if (ps->sniping == 1) {
2427 		if (IgnitePlayersBombs (ps)) {
2428 			ps->sniping = 1;
2429 			ps->d_soll = GoStop;
2430 		}
2431 	}
2432 }								/* RevivePlayer */
2433 
2434 /*
2435  *
2436  */
2437 static void
DoStunned(BMPlayer * ps)2438 DoStunned (BMPlayer * ps)
2439 {
2440 	switch ((ps->d_look + ps->stunned - 1) % 4 + GoStop + 1) {
2441 	case GoDown:
2442 		SetSpriteAnime (ps->sprite, SpriteStopDown);
2443 		break;
2444 	case GoUp:
2445 		SetSpriteAnime (ps->sprite, SpriteStopUp);
2446 		break;
2447 	case GoLeft:
2448 		SetSpriteAnime (ps->sprite, SpriteStopLeft);
2449 		break;
2450 	case GoRight:
2451 		SetSpriteAnime (ps->sprite, SpriteStopRight);
2452 		break;
2453 	}
2454 
2455 	ps->stunned--;
2456 }								/* DoStunned */
2457 
2458 void
DoEvilIll(void)2459 DoEvilIll (void)
2460 {
2461 	BMPlayer *ps1;
2462 
2463 	/* evil-ill countdown */
2464 	for (ps1 = player_stat; ps1 < player_stat + numPlayer; ps1++) {
2465 		if ((ps1->lives) && (ps1->evilill)) {
2466 			if (ps1->evilill == 1)
2467 				/* Too long! Take a hit. */
2468 				ps1->dying = DEAD_TIME;
2469 			ps1->evilill--;
2470 		}
2471 	}
2472 }
2473 
2474 /*
2475  *
2476  */
2477 static void
DoDie(BMPlayer * ps)2478 DoDie (BMPlayer * ps)
2479 {
2480 	if (ps->dying == DEAD_TIME) {
2481 		SetSpriteMode (ps->sprite, SPM_MAPPED);
2482 	}
2483 	ps->dying--;
2484 
2485 	if (ps->lives > 1) {
2486 		switch (ps->d_look) {
2487 		case GoLeft:
2488 			SetSpriteAnime (ps->sprite, SpriteDamagedLeft);
2489 			break;
2490 		case GoUp:
2491 			SetSpriteAnime (ps->sprite, SpriteDamagedUp);
2492 			break;
2493 		case GoRight:
2494 			SetSpriteAnime (ps->sprite, SpriteDamagedRight);
2495 			break;
2496 		default:
2497 			SetSpriteAnime (ps->sprite, SpriteDamagedDown);
2498 			break;
2499 		}
2500 	}
2501 	else {
2502 		switch (ps->d_look) {
2503 		case GoLeft:
2504 			SetSpriteAnime (ps->sprite, SpriteDeadLeft);
2505 			break;
2506 		case GoUp:
2507 			SetSpriteAnime (ps->sprite, SpriteDeadUp);
2508 			break;
2509 		case GoRight:
2510 			SetSpriteAnime (ps->sprite, SpriteDeadRight);
2511 			break;
2512 		default:
2513 			SetSpriteAnime (ps->sprite, SpriteDeadDown);
2514 			break;
2515 		}
2516 	}
2517 }								/* DoDie */
2518 
2519 /*
2520  *
2521  */
2522 XBBool
CheckPlayerNear(int x,int y)2523 CheckPlayerNear (int x, int y)
2524 {
2525 	int player;
2526 
2527 	for (player = 0; player < numPlayer; player++) {
2528 		if ((ABS (x * BLOCK_WIDTH - player_stat[player].x) < BLOCK_WIDTH) &&
2529 			(ABS (y * BLOCK_HEIGHT - BLOCK_HEIGHT - player_stat[player].y) < BLOCK_HEIGHT)) {
2530 			return XBTrue;
2531 		}
2532 	}
2533 	return XBFalse;
2534 }								/* CheckPlayerNear */
2535 
2536 /*
2537  *
2538  */
2539 void
DoAllPlayers(int game_time,int * active_player)2540 DoAllPlayers (int game_time, int *active_player)
2541 {
2542 	int spm_mode;
2543 	int i, p, player;
2544 	int plist[MAX_PLAYER];		// SMPF
2545 
2546 	/* if time is over, kill them all */
2547 	if (game_time == (GAME_TIME - DEAD_TIME + 1)) {
2548 		for (player = 0; player < numPlayer; player++) {
2549 			if (player_stat[player].lives > 0) {
2550 				player_stat[player].lives = 1;
2551 				player_stat[player].dying = DEAD_TIME;
2552 			}
2553 		}
2554 	}
2555 
2556 	for (i = 0; i < numPlayer; i++) {
2557 		plist[i] = i;
2558 	}
2559 	for (i = numPlayer - 1; i > 0; i--) {
2560 		p = GameRandomNumber (i + 1);
2561 		player = plist[p];
2562 		plist[p] = plist[i];
2563 		plist[i] = player;
2564 	}
2565 
2566 	/* check player status */
2567 	for (p = 0; p < numPlayer; p++) {
2568 		/* to permute player when drawing and stunning */
2569 		/* quick and dirty but hopefully it solves some problems */
2570 		player = plist[p];
2571 
2572 		if (player_stat[player].lives != 0) {
2573 
2574 			switch (player_stat[player].dying) {
2575 			case 0:
2576 				/* player is alive and ... */
2577 				if (player_stat[player].morphed) {
2578 					/* ... or morphed */
2579 					DoMorph (player_stat + player);
2580 				}
2581 				else if (player_stat[player].stunned) {
2582 					if (player_stat[player].farted) {
2583 						/* (galatius) */
2584 						DoWalk (player_stat + player, game_time);
2585 						DoStunned (player_stat + player);
2586 						player_stat[player].farted--;
2587 					}
2588 					else {
2589 						/* ... and stunned */
2590 						DoStunned (player_stat + player);
2591 					}
2592 				}
2593 				else {
2594 					/* ... walks around */
2595 					DoWalk (player_stat + player, game_time);
2596 				}
2597 				/* added by Galatius */
2598 				if (player_stat[player].smelly) {
2599 					player_stat[player].smelly--;
2600 				}
2601 				if (player_stat[player].daleifing) {
2602 					player_stat[player].daleifing--;
2603 				}
2604 				break;
2605 
2606 			case 1:
2607 				/* try to revive player */
2608 				RevivePlayer (player_stat + player, active_player);
2609 				break;
2610 
2611 			default:
2612 				/* player is dying */
2613 				DoDie (player_stat + player);
2614 				break;
2615 			}
2616 		}
2617 		else {
2618 			if (player_stat[player].revive) {
2619 				if (player_stat[player].cloaking < 0) {
2620 					player_stat[player].cloaking++;
2621 					if (player_stat[player].cloaking & 0x01) {
2622 						spm_mode = player_stat[player].disp;
2623 					}
2624 					else {
2625 						spm_mode = SPM_UNMAPPED;
2626 					}
2627 				}
2628 				else
2629 					spm_mode = SPM_MAPPED;
2630 				SetSpriteMode (player_stat[player].sprite, spm_mode);
2631 				SetSpriteAnime (player_stat[player].sprite, SpriteZombie);
2632 
2633 			}
2634 		}
2635 	}
2636 }								/* DoAllPlayers */
2637 
2638 /*
2639  *
2640  */
2641 void
CheckPlayerHit(void)2642 CheckPlayerHit (void)
2643 {
2644 	int player;
2645 	int gridx, gridy;
2646 
2647 	for (player = 0; player < numPlayer; player++) {
2648 		gridx = (player_stat[player].x + (BLOCK_WIDTH >> 1)) / BLOCK_WIDTH;
2649 		gridy = (player_stat[player].y + (BLOCK_HEIGHT >> 1)) / BLOCK_HEIGHT + 1;
2650 		if (0 != player_stat[player].lives &&
2651 			0 == player_stat[player].invincible &&
2652 			0 == player_stat[player].morphed &&
2653 			0 == player_stat[player].dying && CheckExplosion (gridx, gridy)) {
2654 			player_stat[player].dying = DEAD_TIME;
2655 		}
2656 	}
2657 }								/* CheckPlayerHit */
2658 
2659 /*
2660  * check if local players are away, make them bot, reset away flag
2661  */
2662 void
Player_CheckLocalAway(void)2663 Player_CheckLocalAway (void)
2664 {
2665 	BMPlayer *ps;
2666 	for (ps = player_stat; ps < player_stat + numPlayer; ps++) {
2667 		if (ps->localDisplay >= 0) {
2668 			if (ps->away) {
2669 				ps->bot = XBTrue;
2670 			}
2671 			else {
2672 				ps->away = XBTrue;
2673 			}
2674 		}
2675 	}
2676 }								/* Player_CheckLocalAway */
2677 
2678 /*
2679  * check if all local players are bots
2680  */
2681 XBBool
Player_CheckLocalBot(void)2682 Player_CheckLocalBot (void)
2683 {
2684 	BMPlayer *ps;
2685 	for (ps = player_stat; ps < player_stat + numPlayer; ps++) {
2686 		if (ps->localDisplay >= 0 && !ps->bot) {
2687 			return XBFalse;
2688 		}
2689 	}
2690 	return XBTrue;
2691 }								/* Player_CheckLocalBot */
2692 
2693 /*
2694  * determine action for all (local) bots
2695  */
2696 void
Player_BotAction(PlayerAction * pa)2697 Player_BotAction (PlayerAction * pa)
2698 {
2699 	BMPlayer *ps;
2700 	for (ps = player_stat; ps < player_stat + numPlayer; ps++) {
2701 		if (ps->bot && ps->localDisplay >= 0) {
2702 			gestionBot (player_stat, pa, ps->id, numPlayer);
2703 		}
2704 	}
2705 }								/* Player_BotAction */
2706 
2707 /*
2708  * de/activate bot
2709  */
2710 void
Player_ActivateBot(BMPlayer * ps,XBBool activate)2711 Player_ActivateBot (BMPlayer * ps, XBBool activate)
2712 {
2713 	assert (ps != NULL);
2714 	ps->away = activate;
2715 	if (ps->bot == activate) {
2716 		return;
2717 	}
2718 	ps->bot = activate;
2719 	if (activate) {
2720 		SetMessage (N_("Bot Activated"), XBFalse);
2721 	}
2722 	else {
2723 		SetMessage (N_("Bot Deactivated"), XBFalse);
2724 	}
2725 }								/* Player_ActivateBot */
2726 
2727 /*
2728  * return if player is local bot
2729  */
2730 XBBool
Player_isLocalBot(BMPlayer * ps)2731 Player_isLocalBot (BMPlayer * ps)
2732 {
2733 	assert (ps != NULL);
2734 	return (ps->bot && ps->localDisplay >= 0);
2735 }								/* Player_isLocalBot */
2736 
2737 /*
2738  * end of file player.c
2739  */
2740