1 /*
2 * Programm XBLAST V1.2.14 or higher
3 * (C) by Oliver Vogel (e-mail: vogel@ikp.uni-koeln.de)
4 * May 9th 1996
5 * started August 1993
6 *
7 * Bot by Didier PLANTET (e-mail: plantet@info.enserb.u-bordeaux.fr)
8 * and Gr�goire ROBERT (e-mail : robert@info.enserb.u-bordeaux.fr)
9 * File: bot.c
10 * Bot IA ...
11 *
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public Licences as published
15 * by the Free Software Foundation; either version 2; or (at your option)
16 * any later version
17 *
18 * This program is distributed in the hope that it will entertaining,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
21 * Publis License for more details.
22 *
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27
28 #include "xblast.h"
29
30 #define _BOT_C
31 #define BOMB_STEP 2
32 #define NUM_FUSES 3
33
34 #define PROB_POSER 10
35 #define PROB_SWAP 100
36
37 #define BONUS_EXPLOSE 40
38 #define BONUS_TUE 60
39 #define BONUS_SIMPLE 100
40 #define BONUS_EXTRA 200
41 #define MALUS_MORT -1000
42
43 #define SLOW_SPEED 16
44 #define NORMAL_SPEED 8
45 #define FAST_SPEED 4
46
47 typedef struct coord
48 {
49 short x, y;
50 short temps;
51 short malus;
52 struct coord *suivant;
53 } coord;
54
55 static int fuse_times[NUM_FUSES] = { SHORT_FUSE, BOMB_TIME, LONG_FUSE };
56
57 /* Tableau des bombes */
58 /*static Explosion *laby_bomb[MAZE_W][MAZE_H];*/
59 /* Liste des bombes */
60 static Explosion bombes_tmp[100];
61 /* Tableau des cases dangereuses : temps avant explosion */
62 static int laby_perf[MAZE_W][MAZE_H];
63 /* Nb de points dans chaque direction */
64 static int vote[NB_DIR];
65 /* Vaut VRAI si je pose */
66 static int vote_poser;
67 /* Vaut VRAI si je swappe */
68 static int vote_swap;
69 /* Vaut VRAI si j'effectue une action sp�ciale (appui sur +) */
70 static int vote_action_speciale;
71 /* Tableau des cases visit�es (bool�en) */
72 static int laby_visit[MAZE_W][MAZE_H];
73 /* Tableau des cases disparaissant */
74 static int laby_shrink[MAZE_W][MAZE_H];
75
76 static int perf_max[NB_DIR];
77 static coord *file;
78
79 static int gameTime;
80
81 static BMPlayer *statut_joueurs;
82 /* Mon num�ro � moi */
83 static int num_bot;
84 static int nb_joueurs;
85 static int nb_ennemis_vivants;
86 static int temps_jeu;
87 /* La duree de deplacement entre 2 cases */
88 static int duree_deplacement;
89
90 /* Score accord� au bonus du niveau */
91 static int bonus_extra;
92
93 int dirige_vers_bonus (int x, int y, int dir);
94 /* Fouf lenteur -- *//* static int trace; */
95
96 void
SetBotTime(int game_time)97 SetBotTime (int game_time)
98 {
99 gameTime = game_time;
100 }
101
102 coord *
creer_coord(int x,int y,int temps,int malus)103 creer_coord (int x, int y, int temps, int malus)
104 {
105 coord *c = (coord *) malloc (sizeof (coord));
106 c->x = x;
107 c->y = y;
108 c->temps = temps;
109 c->malus = malus;
110 c->suivant = NULL;
111
112 return c;
113 }
114
115 void
enfiler(int x,int y,int temps,int malus)116 enfiler (int x, int y, int temps, int malus)
117 {
118 coord *tmpc;
119 coord *c = creer_coord (x, y, temps, malus);
120
121 if (file == NULL)
122 file = c;
123 else {
124 tmpc = file;
125 while (tmpc->suivant != NULL)
126 tmpc = tmpc->suivant;
127 tmpc->suivant = c;
128 }
129 }
130
131 coord *
defiler(void)132 defiler (void)
133 {
134 coord *c = file;
135
136 file = file->suivant;
137
138 return c;
139 }
140
141 /* Renvoie le nb de murs m'entourant */
142 int
test_murs(BMPlayer * ps)143 test_murs (BMPlayer * ps)
144 {
145 int x = ps->x / BLOCK_WIDTH;
146 int y = ps->y / BLOCK_HEIGHT + 1;
147 int nb_murs = 0;
148
149 if (CheckMaze (x, y - 1)) {
150 vote[UP] = MALUS_MORT;
151 nb_murs++;
152 }
153 if (CheckMaze (x - 1, y)) {
154 vote[LEFT] = MALUS_MORT;
155 nb_murs++;
156 }
157 if (CheckMaze (x, y + 1)) {
158 vote[DOWN] = MALUS_MORT;
159 nb_murs++;
160 }
161 if (CheckMaze (x + 1, y)) {
162 vote[RIGHT] = MALUS_MORT;
163 nb_murs++;
164 }
165
166 return nb_murs;
167 }
168
169 /*Explosion *
170 foundBomb (int x, int y)
171 {
172 Explosion *p;
173
174 for (p = expl_list; p != NULL; p = p->next)
175 if (p->x == x && p->y == y)
176 return p;
177
178 return NULL;
179 }*/
180
181 Explosion *
bombe_trouvee_tmp(int x,int y)182 bombe_trouvee_tmp (int x, int y)
183 {
184 int i;
185 for (i = 0; i < 100; i++)
186 if (bombes_tmp[i].range != -1 && bombes_tmp[i].x == x && bombes_tmp[i].y == y)
187 return &bombes_tmp[i];
188
189 return NULL;
190 }
191
192 /*void
193 developpe_bombe (int range, int mazex, int mazey, int type)
194 {
195 Explosion *p;
196 int i,j;
197
198 // right
199 for (i = 1; (i <= range) && CheckMazeOpen(mazex+i-1,mazey) ; i ++)
200 if (mazex+i < MAZE_W)
201 if (laby_perf[mazex][mazey] + i < laby_perf[mazex+i][mazey])
202 {
203 laby_perf[mazex+i][mazey] = laby_perf[mazex][mazey] + i;
204 p = CheckBomb (mazex+i, mazey);
205 if (p != NULL && p->dir == GoStop)
206 developpe_bombe (p->range, mazex+i, mazey, BMTnormal);
207 }
208
209 // Left
210 for (i = 1; (i <= range) && CheckMazeOpen(mazex-i+1,mazey) ; i ++)
211 if (mazex-i >= 0)
212 if (laby_perf[mazex][mazey] + i < laby_perf[mazex-i][mazey])
213 {
214 laby_perf[mazex-i][mazey] = laby_perf[mazex][mazey] + i;
215 p = CheckBomb (mazex-i, mazey);
216 if (p != NULL && p->dir == GoStop)
217 developpe_bombe (p->range, mazex-i, mazey, BMTnormal);
218 }
219
220 // Down
221 for (i = 1; (i <= range) && CheckMazeOpen(mazex,mazey+i-1) ; i ++)
222 if (mazey+i < MAZE_H)
223 if (laby_perf[mazex][mazey] + i < laby_perf[mazex][mazey+i])
224 {
225 laby_perf[mazex][mazey+i] = laby_perf[mazex][mazey] + i;
226 p = CheckBomb (mazex, mazey+i);
227 if (p != NULL && p->dir == GoStop)
228 developpe_bombe (p->range, mazex, mazey+i, BMTnormal);
229 }
230
231 // Up
232 for (i = 1; (i <= range) && CheckMazeOpen(mazex,mazey-i+1) ; i ++)
233 if (mazey-i >= 0)
234 if (laby_perf[mazex][mazey] + i < laby_perf[mazex][mazey-i])
235 {
236 laby_perf[mazex][mazey-i] = laby_perf[mazex][mazey] + i;
237 p = CheckBomb (mazex, mazey-i);
238 if (p != NULL && p->dir == GoStop)
239 developpe_bombe (p->range, mazex, mazey-i, BMTnormal);
240 }
241
242
243 if (type == BMTnapalm)
244 for (i= -2; i<=2; i++) {
245 if (mazex+i < MAZE_W && mazex+i >= 0)
246 developpe_bombe (range/(ABS(i)+1), mazex+i, mazey, BMTnormal);
247 if (mazey+i < MAZE_H && mazey+i >= 0)
248 developpe_bombe (range/(ABS(i)+1), mazex, mazey+i, BMTnormal);
249 }
250
251 if (type == BMTgrenade)
252 if (range == 1) {
253 developpe_bombe(0, mazex-1, mazey-1, BMTblastnow);
254 developpe_bombe(0, mazex+1, mazey-1, BMTblastnow);
255 developpe_bombe(0, mazex-1, mazey+1, BMTblastnow);
256 developpe_bombe(0, mazex+1, mazey+1, BMTblastnow);
257 } else {
258 for (i = -((range)-1); i<=((range)-1); i++) {
259 for (j = -((range)-1); j<=((range)-1); j++) {
260 developpe_bombe (1, mazex+i, mazey+j, BMTblastnow);
261 }
262 }
263 }
264 }*/
265
266 void
developpe_bombe_tmp(int range,int mazex,int mazey,int type,int count)267 developpe_bombe_tmp (int range, int mazex, int mazey, int type, int count)
268 {
269 // Explosion *p;
270 int i, j;
271
272 /* right */
273 for (i = 1; (i <= range) && CheckMazeOpen (mazex + i - 1, mazey); i++)
274 if (mazex + i < MAZE_W)
275 if (laby_perf[mazex][mazey] + i < laby_perf[mazex + i][mazey])
276 laby_perf[mazex + i][mazey] = laby_perf[mazex][mazey] + i * count;
277
278 /* Left */
279 for (i = 1; (i <= range) && CheckMazeOpen (mazex - i + 1, mazey); i++)
280 if (mazex - i >= 0)
281 if (laby_perf[mazex][mazey] + i < laby_perf[mazex - i][mazey])
282 laby_perf[mazex - i][mazey] = laby_perf[mazex][mazey] + i * count;
283
284 /* Down */
285 for (i = 1; (i <= range) && CheckMazeOpen (mazex, mazey + i - 1); i++)
286 if (mazey + i < MAZE_H)
287 if (laby_perf[mazex][mazey] + i < laby_perf[mazex][mazey + i])
288 laby_perf[mazex][mazey + i] = laby_perf[mazex][mazey] + i * count;
289
290 /* Up */
291 for (i = 1; (i <= range) && CheckMazeOpen (mazex, mazey - i + 1); i++)
292 if (mazey - i >= 0)
293 if (laby_perf[mazex][mazey] + i < laby_perf[mazex][mazey - i])
294 laby_perf[mazex][mazey - i] = laby_perf[mazex][mazey] + i * count;
295
296 if (type == BMTnapalm)
297 for (i = -2; i <= 2; i++) {
298 if (mazex + i < MAZE_W && mazex + i >= 0)
299 developpe_bombe_tmp (range / (ABS (i) + 1), mazex + i, mazey, BMTnormal, count);
300 if (mazey + i < MAZE_H && mazey + i >= 0)
301 developpe_bombe_tmp (range / (ABS (i) + 1), mazex, mazey + i, BMTnormal, count);
302 }
303
304 if (type == BMTgrenade) {
305 if (range == 1) {
306 developpe_bombe_tmp (0, mazex - 1, mazey - 1, BMTblastnow, count);
307 developpe_bombe_tmp (0, mazex + 1, mazey - 1, BMTblastnow, count);
308 developpe_bombe_tmp (0, mazex - 1, mazey + 1, BMTblastnow, count);
309 developpe_bombe_tmp (0, mazex + 1, mazey + 1, BMTblastnow, count);
310 }
311 else {
312 for (i = -((range) - 1); i <= ((range) - 1); i++) {
313 for (j = -((range) - 1); j <= ((range) - 1); j++) {
314 developpe_bombe_tmp (1, mazex + i, mazey + j, BMTblastnow, count);
315 }
316 }
317 }
318 }
319 }
320
321 /* Traduit une direction en dx et dy */
322 void
conversion_direction(int dir,int * dx,int * dy)323 conversion_direction (int dir, int *dx, int *dy)
324 {
325 *dx = 0;
326 *dy = 0;
327 switch (dir) {
328 case UP:
329 *dy = -1;
330 break;
331 case DOWN:
332 *dy = 1;
333 break;
334 case LEFT:
335 *dx = -1;
336 break;
337 case RIGHT:
338 *dx = 1;
339 }
340 }
341
342 /* Les bonus extras sont-ils positifs ou n�gatifs ? */
343 void
def_score_extra(BMPlayer * ps)344 def_score_extra (BMPlayer * ps)
345 {
346 bonus_extra = BONUS_EXTRA;
347 /* La tortue */
348 if (specialExtraFunc == SpecialExtraSlow) {
349 if (!ps->iniextra_flags) {
350 bonus_extra = -BONUS_SIMPLE / 2;
351 }
352 else {
353 if (!ps->revextra_flags)
354 bonus_extra = -BONUS_SIMPLE / 2;
355 else
356 bonus_extra = 0; /* Si je suis d�j� lent, reprendre une tortue ne change rien */
357 }
358 }
359 /* Le "bonus" invisible qui fait tourner */
360 if (specialExtraFunc == SpecialExtraStunOthers) {
361 bonus_extra = -2 * BONUS_SIMPLE;
362 }
363 /* La seringue */
364 if (specialExtraFunc == SpecialExtraJunkie && ps->junkie == 0) {
365 /* Si j'y ai d�j� touch�, j'ai int�r�t � en reprendre... */
366 bonus_extra = -5 * BONUS_SIMPLE;
367 }
368 /* La mort imm�diate */
369 if (specialExtraFunc == SpecialExtraPoison) {
370 bonus_extra = -10 * BONUS_SIMPLE;
371 }
372
373 }
374
375 /* Un bonus sur la case ? */
376 int
score_bonus(int x,int y)377 score_bonus (int x, int y)
378 {
379 int bonus;
380
381 bonus = GetBlockExtra (x, y);
382
383 if (bonus == BTBomb || bonus == BTRange)
384 bonus = BONUS_SIMPLE + 200;
385 else if (bonus == BTSpecial || bonus == BTExtra) {
386 if (specialExtraFunc != SpecialExtraPoison) {
387 bonus = bonus_extra;
388 }
389 else {
390 bonus = -BONUS_SIMPLE;
391 }
392
393 }
394 else /* if (bonus == BTSwapper)
395 bonus = BONUS_EXTRA;
396 else */ if (bonus == BTEvil)
397 bonus = -BONUS_SIMPLE;
398
399 else
400 bonus = 0;
401 return bonus;
402 }
403
404 /* Est-il int�ressant de poser sur cette case ? */
405 int
score_explose(int x,int y,int portee_bombe)406 score_explose (int x, int y, int portee_bombe)
407 {
408 int explose = 0;
409 int dir, dx, dy;
410 int i;
411
412 for (dir = 1; dir < NB_DIR; dir++) {
413 conversion_direction (dir, &dx, &dy);
414 i = 1;
415 while (CheckMazeFree (x + i * dx, y + i * dy) && i <= portee_bombe)
416 i++;
417 /* Y a-t-il un mur � d�truire ? Et sinon, un bonus ? */
418 if (GetBlockExtra (x + i * dx, y + i * dy) == BTExtra)
419 explose += BONUS_EXPLOSE;
420 else
421 explose -= (score_bonus (x + i * dx, y + i * dy) / 4);
422 }
423 explose += 75;
424 return explose;
425 }
426
427 /* Est-ce que poser ici va menacer un autre joueur ? */
428 int
score_tue(int x,int y,int portee_bombe)429 score_tue (int x, int y, int portee_bombe)
430 {
431 int tue = 0;
432 int xmin = -1, xmax = -1, ymin = -1, ymax = -1;
433 int j, jx, jy;
434 int points;
435 BMPlayer *ps;
436
437 /* Quelles cases puis-je atteindre ? */
438 for (j = 1; j <= portee_bombe; j++) {
439 if (xmin == -1 && (!CheckMazeFree (x - j, y) || j == portee_bombe))
440 xmin = x - j;
441 if (xmax == -1 && (!CheckMazeFree (x + j, y) || j == portee_bombe))
442 xmax = x + j;
443 if (ymin == -1 && (!CheckMazeFree (x, y - j) || j == portee_bombe))
444 ymin = y - j;
445 if (ymax == -1 && (!CheckMazeFree (x, y + j) || j == portee_bombe))
446 ymax = y + j;
447 }
448 nb_ennemis_vivants = 0;
449 for (j = 0; j < nb_joueurs; j++) {
450 ps = statut_joueurs + j;
451
452 /* Le joueur n'est pas le bot et vit encore */
453 if ((j != num_bot) && (ps->lives != 0)) {
454 jx = ps->x / BLOCK_WIDTH;
455 jy = ps->y / BLOCK_HEIGHT + 1;
456
457 points = BONUS_TUE;
458
459 /* Si le joueur est mon partenaire.... je vais �viter de le tuer ! */
460 if (ps->team == (statut_joueurs + num_bot)->team)
461 points = -points;
462 else
463 nb_ennemis_vivants++;
464
465 /* Je suis sur la m�me colonne */
466 if ((x == jx) && ((ymin <= jy) && (jy <= ymax)))
467 tue += points;
468
469 /* Je suis sur la m�me ligne (et pas sur la m�me colonne) */
470 if ((y == jy) && (x != jx) && ((xmin <= jx) && (jx <= xmax)))
471 tue += points;
472
473 /* Si le joueur a une mauvaise mort (poseuse, lenteur, mini, non-poseuse,
474 malfunction, teleport, ou *seringue*), je dois l'�viter */
475 if ((x == jx) && (y == jy)) {
476 if ((ps->illness == IllBomb) ||
477 (ps->illness == IllSlow) ||
478 (ps->illness == IllMini) ||
479 (ps->illness == IllEmpty) ||
480 (ps->illness == IllMalfunction) || (ps->illness == IllTeleport) || (ps->junkie))
481 tue -= BONUS_SIMPLE;
482 }
483 /* sinon, j'essaie toujours de m'en approcher (s'il n'est pas mon partenaire) */
484 else
485 tue += points;
486 }
487 }
488 return tue;
489 }
490
491 /* Est-ce que je risque de me faire shrinker sur cette case ? */
492 int
score_shrink(int x,int y,int temps)493 score_shrink (int x, int y, int temps)
494 {
495 int score = 0;
496
497 temps += temps_jeu;
498 if (laby_shrink[x][y] - temps <= 16)
499 score = MALUS_MORT;
500 else if (laby_shrink[x][y] - temps <= 50)
501 score = -BONUS_EXTRA;
502 else if (laby_shrink[x][y] - temps <= 100)
503 score = -BONUS_SIMPLE;
504
505 return score;
506 }
507
508 /* Teste le danger et l'int�r�t d'une case... puis poursuit le parcours par niveau */
509 void
teste_case(coord * c,int dir_init,BMPlayer * ps)510 teste_case (coord * c, int dir_init, BMPlayer * ps)
511 {
512 int perf = laby_perf[c->x][c->y] - c->temps;
513 int portee_bombe = (ps->illness == IllMini) ? 1 : ps->range;
514 int score, malus;
515 int invincible = ps->invincible - c->temps;
516 int tourne = ps->stunned - c->temps;
517 int dir, dx, dy;
518
519 if (invincible > 0)
520 perf += invincible;
521 if (tourne < 0)
522 tourne = 0;
523
524 /* Une bombe explosera sur le passage */
525 if (perf <= 4)
526 return;
527
528 /* La case dispara�tra */
529 if (score_shrink (c->x, c->y, c->temps) == MALUS_MORT)
530 return;
531
532 score = score_bonus (c->x, c->y);
533 if (score <= -500)
534 return;
535
536 /* Mise � jour du malus (score n�gatif le + faible du chemin) */
537 malus = MIN (c->malus, score);
538
539 /* Calcul du score de la case */
540 score += score_explose (c->x, c->y, portee_bombe);
541 score += score_tue (c->x, c->y, portee_bombe);
542 score += score_shrink (c->x, c->y, c->temps);
543
544 /* Mise � jour de la performance maximale de la direction dir_init */
545 perf += score;
546 if (perf > 10 * LONG_FUSE)
547 perf += malus;
548 perf_max[dir_init] = MAX (perf_max[dir_init], perf);
549
550 for (dir = 1; dir < NB_DIR; dir++) {
551 conversion_direction (dir, &dx, &dy);
552 /* Si je ne suis pas d�j� pass� par l�, s'il n'y a ni mur, ni bombe, je place la case dans la file */
553 if (!laby_visit[c->x + dx][c->y + dy] && !CheckMaze (c->x + dx, c->y + dy)
554 ) {
555 if (!ps->kick) {
556 if (!CheckBomb (c->x + dx, c->y + dy)) {
557 enfiler (c->x + dx, c->y + dy, c->temps + duree_deplacement + tourne, malus);
558 laby_visit[c->x + dx][c->y + dy] = 1;
559 }
560
561 }
562 else {
563 enfiler (c->x + dx, c->y + dy, c->temps + duree_deplacement + tourne, malus);
564 laby_visit[c->x + dx][c->y + dy] = 1;
565 }
566 }
567 }
568 }
569
570 /* Remplissage du tableau laby_shrink (en d�but de niveau) */
571 void
init_laby_shrink()572 init_laby_shrink ()
573 {
574 ShrinkGeneric *shrink_ptr = GetShrinkPtr ();
575 XBScrambleData *scramble = GetScrDraw ();
576 int temps;
577 int x, y;
578 unsigned mask;
579
580 for (x = 0; x < MAZE_W; x++)
581 for (y = 0; y < MAZE_H; y++)
582 laby_shrink[x][y] = 2 * GAME_TIME;
583
584 /* La liste point�e par shrink_ptr se termine par une cellule (2 * GAME_TIME, 0, 0) */
585 while (shrink_ptr->time < 2 * GAME_TIME) {
586 temps = shrink_ptr->time;
587 x = shrink_ptr->x;
588 y = shrink_ptr->y;
589 if (laby_shrink[x][y] > temps)
590 laby_shrink[x][y] = temps;
591 shrink_ptr++;
592 }
593
594 /* Blocs surgissant sur le plateau */
595 temps = scramble->time - 4;
596 for (y = 0; y < MAZE_H; y++) {
597 if (0 != scramble->row[y]) {
598 for (x = 0, mask = 1; x < MAZE_W; x++, mask <<= 1) {
599 if (mask & scramble->row[y]) {
600 if (laby_shrink[x][y] > temps)
601 laby_shrink[x][y] = temps;
602 }
603 }
604 }
605 }
606
607 /* for (y = 0; y < MAZE_H; y++) {
608 for (x = 0; x < MAZE_W; x++)
609 fprintf (stderr, "%d ", laby_shrink[x][y]);
610 fprintf (stderr, "\n");
611 }*/
612 }
613
614 /* Aucune case n'a �t� visit�e (d�but d'un parcours par niveau) */
615 void
init_laby_visit(int x,int y)616 init_laby_visit (int x, int y)
617 {
618 int mazex, mazey;
619
620 for (mazex = 0; mazex < MAZE_W; mazex++)
621 for (mazey = 0; mazey < MAZE_H; mazey++)
622 laby_visit[mazex][mazey] = 0;
623
624 /* memset (&laby_visit, 0, MAZE_W * MAZE_H * sizeof (int));*/
625
626 laby_visit[x][y] = 1;
627 }
628
629 static BMDirection turn_clockwise[MAX_DIR] = {
630 GoStop, GoRight, GoUp, GoLeft, GoDown, GoDefault
631 };
632
633 static BMDirection turn_anticlockwise[MAX_DIR] = {
634 GoStop, GoLeft, GoDown, GoRight, GoUp, GoDefault
635 };
636
637 static BMDirection turn_opposite[MAX_DIR] = {
638 GoStop, GoDown, GoRight, GoUp, GoLeft, GoDefault
639 };
640
641 void
calc_laby_perf()642 calc_laby_perf ()
643 {
644 int player;
645 int i, j, k;
646 int dx, dy;
647 int temps;
648 Explosion *p;
649 Explosion *p2;
650
651 /* On traite d'abord les bombes en train d'exploser (count > 0) */
652 for (i = 0; i < 100; i++) {
653 p = &bombes_tmp[i];
654
655 if (p->range == -1)
656 continue;
657
658 if (p->count < 0)
659 continue;
660
661 if (laby_perf[p->x][p->y] > -p->count) {
662 laby_perf[p->x][p->y] = -p->count;
663 developpe_bombe_tmp (p->range, p->x, p->y, p->type, -p->count);
664 }
665 else
666 developpe_bombe_tmp (p->range, p->x, p->y, BMTnormal, -p->count);
667
668 p->range = -1;
669 }
670
671 for (temps = 0; temps < LONG_FUSE; temps++) { /* On deplace case par case */
672 for (i = 0; i < 100; i++) { /* Pour chaque bombe */
673 p = &bombes_tmp[i];
674
675 if (p->range == -1)
676 continue;
677
678 if (temps == -p->count || laby_perf[p->x][p->y] <= temps) { /* On explose la */
679 if (laby_perf[p->x][p->y] > -p->count) {
680 laby_perf[p->x][p->y] = -p->count;
681 developpe_bombe_tmp (p->range, p->x, p->y, p->type, -p->count);
682 }
683 else
684 developpe_bombe_tmp (p->range, p->x, p->y, BMTnormal, -p->count);
685
686 p->range = -1;
687 continue;
688 }
689
690 if (p->dir == GoStop) {
691 continue;
692 }
693 conversion_direction (p->dir, &dx, &dy);
694 /* Si on cogne une bombe */
695 if (p->dx * dx >= 0 && p->dy * dy >= 0 && bombe_trouvee_tmp (p->x + dx, p->y + dy)) {
696 if (doBombClick == BombClickNone) {
697 p->dir = GoStop;
698 p->dx = 0;
699 p->dy = 0;
700 }
701 else if (doBombClick == BombClickInitial) {
702 p->dir = initialBombDir;
703 conversion_direction (p->dir, (int *)&p->dx, (int *)&p->dy);
704 }
705 else if (doBombClick == BombClickThru) {
706 }
707 else if (doBombClick == BombClickSnooker) {
708 p2 = bombe_trouvee_tmp (p->x + dx, p->y + dy);
709 p2->dir = p->dir;
710 /* On met a 0 l'offset de l'autre direction */
711 p2->dx = p2->dx * ABS (dx);
712 p2->dy = p2->dy * ABS (dy);
713 /* La bombe qui cogne arrete de bouger */
714 p->dir = GoStop;
715 p->dx = 0;
716 p->dy = 0;
717 }
718 else if (doBombClick == BombClickContact) {
719 p->dir = GoStop;
720 p->dx = 0;
721 p->dy = 0;
722 if (laby_perf[p->x][p->y] > -p->count)
723 laby_perf[p->x][p->y] = -p->count;
724 developpe_bombe_tmp (p->range, p->x, p->y, p->type, -p->count);
725 bombes_tmp[i].range = -1;
726 }
727 else if (doBombClick == BombClickContact) {
728 p->dir = turn_clockwise[p->dir];
729 p->dx = 0;
730 p->dy = 0;
731 }
732 else if (doBombClick == BombClickAnticlockwise) {
733 p->dir = turn_anticlockwise[p->dir];
734 p->dx = 0;
735 p->dy = 0;
736 }
737 else if (doBombClick == BombClickRandomdir) {
738 p->dir = (int)(((float)rand () / (RAND_MAX + 1.0)) * (4)) + 1;
739 p->dx = 0;
740 p->dy = 0;
741 }
742 else if (doBombClick == BombClickRebound) {
743 p->dir = turn_opposite[p->dir];
744 }
745 }
746 /* Ou un mur */
747 else if (p->dx == 0 && p->dy == 0 && !CheckMazeFree (p->x + dx, p->y + dy)) {
748 if (doWallClick == BombClickNone) {
749 p->dir = GoStop;
750 p->dx = 0;
751 p->dy = 0;
752 }
753 else if (doWallClick == BombClickInitial) {
754 p->dir = initialBombDir;
755 conversion_direction (p->dir, (int *)&p->dx, (int *)&p->dy);
756 }
757 else if (doWallClick == BombClickThru) {
758 }
759 else if (doWallClick == BombClickContact) {
760 p->dir = GoStop;
761 p->dx = 0;
762 p->dy = 0;
763 if (laby_perf[p->x][p->y] > -p->count)
764 laby_perf[p->x][p->y] = -p->count;
765 developpe_bombe_tmp (p->range, p->x, p->y, p->type, -p->count);
766 bombes_tmp[i].range = -1;
767 }
768 else if (doWallClick == BombClickContact) {
769 p->dir = turn_clockwise[p->dir];
770 p->dx = 0;
771 p->dy = 0;
772 }
773 else if (doWallClick == BombClickAnticlockwise) {
774 p->dir = turn_anticlockwise[p->dir];
775 p->dx = 0;
776 p->dy = 0;
777 }
778 else if (doWallClick == BombClickRandomdir) {
779 p->dir = (BMDirection) (int)((float)rand () / (RAND_MAX + 1.0)) * MAX_DIR;
780 p->dx = 0;
781 p->dy = 0;
782 }
783 else if (doWallClick == BombClickRebound) {
784 p->dir = turn_opposite[p->dir];
785 }
786 }
787 /* Un joueur */
788 else {
789
790 for (player = 0; player < nb_joueurs; player++) {
791 if ((statut_joueurs[player].invincible == 0)
792 && (ABS (p->x * BLOCK_WIDTH + p->dx - statut_joueurs[player].x)
793 < BOMB_STUN_X)
794 && (ABS (p->y * BLOCK_HEIGHT + p->dy
795 - statut_joueurs[player].y - BLOCK_HEIGHT) < BOMB_STUN_Y))
796 break;
797 }
798
799 if (player < nb_joueurs) {
800 if (doPlayerClick == BombClickNone) {
801 p->dir = GoStop;
802 p->dx = 0;
803 p->dy = 0;
804 }
805 else if (doPlayerClick == BombClickInitial) {
806 p->dir = initialBombDir;
807 conversion_direction (p->dir, (int *)&p->dx, (int *)&p->dy);
808 }
809 else if (doPlayerClick == BombClickThru) {
810 }
811 else if (doPlayerClick == BombClickContact) {
812 p->dir = GoStop;
813 p->dx = 0;
814 p->dy = 0;
815 if (laby_perf[p->x][p->y] > -p->count)
816 laby_perf[p->x][p->y] = -p->count;
817 developpe_bombe_tmp (p->range, p->x, p->y, p->type, -p->count);
818 bombes_tmp[i].range = -1;
819 }
820 else if (doPlayerClick == BombClickContact) {
821 p->dir = turn_clockwise[p->dir];
822 p->dx = 0;
823 p->dy = 0;
824 }
825 else if (doPlayerClick == BombClickAnticlockwise) {
826 p->dir = turn_anticlockwise[p->dir];
827 p->dx = 0;
828 p->dy = 0;
829 }
830 else if (doPlayerClick == BombClickRandomdir) {
831 p->dir = (int)(((float)rand () / (RAND_MAX + 1.0)) * (4)) + 1;
832 p->dx = 0;
833 p->dy = 0;
834 }
835 else if (doPlayerClick == BombClickRebound) {
836 p->dir = turn_opposite[p->dir];
837 }
838
839 }
840 }
841
842 conversion_direction (p->dir, &dx, &dy);
843
844 p->dy += dy * BOMB_VY;
845 p->dx += dx * BOMB_VX;
846
847 if (p->dx * dx >= BLOCK_WIDTH / 2) {
848 p->dx -= dx * BLOCK_WIDTH;
849 p->x += dx;
850 }
851
852 if (p->dy * dy >= BLOCK_HEIGHT / 2) {
853 p->dy -= dy * BLOCK_HEIGHT;
854 p->y += dy;
855 }
856 if (p->x < 0)
857 p->x = 0;
858 if (p->y < 0)
859 p->y = 0;
860
861 /* On aime pas tres bien etre sur la trajectoire d'une bombe */
862 laby_perf[p->x][p->y] = MIN (laby_perf[p->x][p->y], 50 * LONG_FUSE - 500 + temps * 4);
863
864 }
865
866 for (i = 0; i < 100; i++) { /* Pour chaque bombe */
867 p = &bombes_tmp[i];
868
869 if (p->range == -1)
870 continue;
871
872 /* Les bombes en train d'exploser ne se repoduisent pas ... */
873 if (p->count <= 0)
874 continue;
875
876 if (p->type == BMTfungus) { /* On developpe les bombes fungus ... */
877 if (p->count == (fuse_times[curBombTime] * 3 / 5)) {
878
879 for (j = -1; j <= 1; j++) {
880 if ((p->x + j < MAZE_W) && (p->x + j > -1)
881 && !CheckMazeSolid (p->x + j, p->y)) {
882 /* On trouve un emplacement libre ... */
883 for (k = 0; k < 100; k++)
884 if (bombes_tmp[k].range == -1)
885 break;
886 bombes_tmp[k].x = p->x + j;
887 bombes_tmp[k].y = p->y;
888 bombes_tmp[k].range = p->range;
889 bombes_tmp[k].type = BMTfungus;
890 bombes_tmp[k].dir = GoStop;
891 bombes_tmp[k].count = fuse_times[curBombTime];
892 }
893
894 if ((p->y + j < MAZE_H) && (p->y + j > -1)
895 && !CheckMazeSolid (p->x, p->y + j)) {
896 /* On trouve un emplacement libre ... */
897 for (k = 0; k < 100; k++)
898 if (bombes_tmp[k].range == -1)
899 break;
900 bombes_tmp[k].x = p->x;
901 bombes_tmp[k].y = p->y + j;
902 bombes_tmp[k].range = p->range;
903 bombes_tmp[k].type = BMTfungus;
904 bombes_tmp[k].dir = GoStop;
905 bombes_tmp[k].count = fuse_times[curBombTime];
906 }
907 }
908 }
909 }
910 }
911 }
912 }
913
914 void
init_laby_perf()915 init_laby_perf ()
916 {
917 int i;
918 int mazex, mazey;
919 Explosion *p;
920
921 for (mazex = 0; mazex < MAZE_W; mazex++)
922 for (mazey = 0; mazey < MAZE_H; mazey++)
923 laby_perf[mazex][mazey] = 50 * LONG_FUSE;
924
925 for (i = 0; i < 100; i++)
926 bombes_tmp[i].range = -1;
927
928 for (p = exploList, i = 1; p != NULL; p = p->next, i++)
929 bombes_tmp[i] = *p;
930
931 calc_laby_perf ();
932 }
933
934 void
init_laby_perf_pose(int x,int y,int range,int count,int type)935 init_laby_perf_pose (int x, int y, int range, int count, int type)
936 {
937 int i;
938 int mazex, mazey;
939 Explosion *p;
940
941 for (mazex = 0; mazex < MAZE_W; mazex++)
942 for (mazey = 0; mazey < MAZE_H; mazey++)
943 laby_perf[mazex][mazey] = 50 * LONG_FUSE;
944
945 for (i = 0; i < 100; i++)
946 bombes_tmp[i].range = -1;
947
948 for (p = exploList, i = 1; p != NULL; p = p->next, i++)
949 bombes_tmp[i] = *p;
950
951 bombes_tmp[i].x = x;
952 bombes_tmp[i].y = y;
953 bombes_tmp[i].range = range;
954 bombes_tmp[i].count = -count;
955 bombes_tmp[i].type = type;
956
957 calc_laby_perf ();
958
959 }
960
961 void
init_laby_perf_biscotte()962 init_laby_perf_biscotte ()
963 {
964 int i;
965 int mazex, mazey;
966 Explosion *p;
967
968 for (mazex = 0; mazex < MAZE_W; mazex++)
969 for (mazey = 0; mazey < MAZE_H; mazey++)
970 laby_perf[mazex][mazey] = 50 * LONG_FUSE;
971
972 for (i = 0; i < 100; i++)
973 bombes_tmp[i].range = -1;
974
975 for (p = exploList, i = 1; p != NULL; p = p->next, i++) {
976 bombes_tmp[i] = *p;
977 if (p->player)
978 if (p->player->id == num_bot)
979 bombes_tmp[i].count = 0;
980 }
981
982 calc_laby_perf ();
983 }
984
985 void
parcours_par_niveau(BMPlayer * ps)986 parcours_par_niveau (BMPlayer * ps)
987 {
988 coord *c;
989 int dir;
990 int x = ps->x / BLOCK_WIDTH;
991 int y = ps->y / BLOCK_HEIGHT + 1;
992 int dx, dy;
993 int malus;
994 int portee_bombe = (ps->illness == IllMini) ? 1 : ps->range;
995
996 /* for (dir = 0; dir < NB_DIR; dir++)
997 perf_max[dir] = 0;
998 */
999 perf_max[STOP] = score_shrink (x, y, ps->stunned);
1000 /* Ajout de la s�curit� et de l'invincibilit� du joueur si la case ne se fait pas shrinker imm�diatement */
1001 if (perf_max[STOP] > MALUS_MORT)
1002 perf_max[STOP] += laby_perf[x][y] + ps->invincible;
1003
1004 /* Ajout des bonus explose et tue si la case est s�re */
1005 if (perf_max[STOP] == 50 * LONG_FUSE) {
1006 perf_max[STOP] += score_explose (x, y, portee_bombe);
1007 perf_max[STOP] += score_tue (x, y, portee_bombe);
1008 }
1009 perf_max[STOP] += 60;
1010
1011 for (dir = 1; dir < NB_DIR; dir++) {
1012 conversion_direction (dir, &dx, &dy);
1013 init_laby_visit (x, y);
1014 /* Eviter mur et shrink imm�diat */
1015 if (!CheckMaze (x + dx, y + dy) && score_shrink (x + dx, y + dy, ps->stunned) > MALUS_MORT
1016 && (dirige_vers_bonus (x, y, dir) != -1))
1017 if (!CheckBomb (x + dx, y + dy)) {
1018 malus = MIN (0, score_bonus (x + dx, y + dy));
1019 enfiler (x + dx, y + dy, duree_deplacement + ps->stunned, malus);
1020 while (file) {
1021 c = defiler ();
1022 teste_case (c, dir, ps);
1023 free (c);
1024 }
1025 }
1026 }
1027 }
1028
1029 /* Renvoie VRAI s'il est possible et int�ressant de poser une bombe */
1030 int
souhaite_poser_bombe(BMPlayer * ps)1031 souhaite_poser_bombe (BMPlayer * ps)
1032 {
1033 int score;
1034 int mazex, mazey;
1035 int portee_bombe = (ps->illness == IllMini) ? 1 : ps->range;
1036 // int j;
1037
1038 mazex = ps->x / BLOCK_WIDTH;
1039 mazey = ps->y / BLOCK_HEIGHT + 1;
1040
1041 /* Est-il possible de poser ? */
1042
1043 /* Pas de bombe sur la case */
1044 if (CheckBomb (mazex, mazey))
1045 return XBFalse;
1046
1047 /* Je n'ai ni la non poseuse, ni la t�l�porte, ni la mal-function */
1048 if (ps->illness == IllEmpty || ps->illness == IllTeleport || ps->illness == IllMalfunction)
1049 return XBFalse;
1050
1051 /* Il me reste des bombes... */
1052 if (ps->bombs == 0)
1053 return XBFalse;
1054
1055 /* Est-il int�ressant de poser ? */
1056 score = score_explose (mazex, mazey, portee_bombe) + score_tue (mazex, mazey, portee_bombe);
1057
1058 // fprintf(stderr," socre expl %i \n",score);
1059 if (score < 0)
1060 return XBFalse;
1061
1062 /* Aucune raison particuli�re de poser... au hasard pr�s */
1063 if (score == 0 && (int)(((float)rand () / (RAND_MAX + 1.0)) * (PROB_POSER)) != 0)
1064 return XBFalse;
1065
1066 /* S'il reste au moins un autre joueur vivant, j'essaie de poser */
1067 return (nb_ennemis_vivants > 0);
1068 }
1069
1070 /* Renvoie VRAI si je me dirige vers un bonus */
1071 int
dirige_vers_bonus(int x,int y,int dir)1072 dirige_vers_bonus (int x, int y, int dir)
1073 {
1074 int dx, dy;
1075
1076 conversion_direction (dir, &dx, &dy);
1077 if ((CheckBonuses2 (x + dx, y + dy)) && (specialExtraFunc == SpecialExtraPoison)) { //fprintf(stderr," field poisoned\n");
1078 return -1; // POISON!!!
1079 }
1080 else {
1081
1082 return CheckBonuses (x + dx, y + dy);
1083 }
1084
1085 }
1086
1087 /* Choix de la meilleure direction */
1088 static void
choix_direction(int * choix_dir,int * max_perf)1089 choix_direction (int *choix_dir, int *max_perf)
1090 {
1091 int dir = 0, dir1 = 0;
1092 static int old_dir = 0;
1093 *choix_dir = STOP;
1094 *max_perf = 0;
1095 for (dir = 0; dir < NB_DIR; dir++) {
1096 /* Ajout d'un petit bonus al�atoire si la case est s�re */
1097 if (perf_max[dir] > 10 * LONG_FUSE)
1098 perf_max[dir] += (int)(((float)rand () / (RAND_MAX + 1.0)) * (10)); //
1099 // GameRandomNumber1 (10);
1100
1101 /* Je choisis la destination ayant la meilleure performance */
1102 // if(dir==old_dir && dir!=0) perf_max[dir]+=50;
1103 if (dir == old_dir && dir == 0)
1104 perf_max[dir] -= 100;
1105 if (perf_max[dir] > *max_perf) {
1106 *max_perf = perf_max[dir];
1107 *choix_dir = dir;
1108 }
1109 else if ((perf_max[dir] == *max_perf) &&
1110 ((int)((float)rand () / (RAND_MAX + 1.0)) * (5) == dir))
1111 *choix_dir = dir;
1112 }
1113 for (dir = 0; dir < NB_DIR; dir++) {
1114
1115 for (dir1 = 0; dir1 < NB_DIR; dir1++) {
1116 if (perf_max[dir] == perf_max[dir1] && dir != dir1) {
1117 if (dir < dir1) {
1118 if (dir == old_dir)
1119 perf_max[dir] += 75;
1120 else
1121 perf_max[dir]++;
1122
1123 }
1124 }
1125 }
1126 }
1127 for (dir = 0; dir < NB_DIR; dir++) {
1128 // fprintf(stderr,"dir %i prfmax %i olddir %i\n",dir, perf_max[dir],old_dir);
1129 if (perf_max[dir] > *max_perf) {
1130 *max_perf = perf_max[dir];
1131 *choix_dir = dir;
1132 }
1133
1134 }
1135 for (dir = 0; dir < NB_DIR; dir++) {
1136 perf_max[dir] = 0;
1137 }
1138 old_dir = *choix_dir;
1139 }
1140
1141 /* Renvoie VRAI si je d�cide d'utiliser la t�l�commande MAINTENANT */
1142 int
test_biscotte(BMPlayer * ps)1143 test_biscotte (BMPlayer * ps)
1144 {
1145 int declenche = XBFalse;
1146 int mes_bombes = 0;
1147 int securite_init;
1148 Explosion *bombe;
1149 int x, y;
1150
1151 x = ps->x / BLOCK_WIDTH;
1152 y = ps->y / BLOCK_HEIGHT + 1;
1153 securite_init = laby_perf[x][y];
1154
1155 /* Parcours de toutes les bombes du plateau */
1156 for (bombe = exploList; bombe != NULL; bombe = bombe->next)
1157 /* Si cette bombe m'appartient... */
1158 if (bombe->player == ps) {
1159 mes_bombes++;
1160 /* ... je la fais exploser ! */
1161 /* laby_perf[bombe->x][bombe->y] = 0;
1162 developpe_bombe (bombe->range, bombe->x, bombe->y, bombe->type); */
1163 init_laby_perf_biscotte ();
1164 }
1165 if ((mes_bombes > 0) && ((laby_perf[x][y] == securite_init) || (ps->invincible > 5)))
1166 declenche = XBTrue;
1167
1168 return declenche;
1169 }
1170
1171 /* Renvoie VRAI si j'ai envie de swapper MAINTENANT.*/
1172 int
test_swap(BMPlayer * ps,int perf)1173 test_swap (BMPlayer * ps, int perf)
1174 {
1175 int vote_swap = XBFalse;
1176 int partenaire;
1177 int equipe_complete = XBFalse;
1178 int joueur;
1179
1180 /* Swap al�atoire si j'ai au moins 2 swaps */
1181 /* if (ps->swapposition > 1)
1182 vote_swap = (GameRandomNumber1 (PROB_SWAP) == 0); */
1183
1184 /* Si nous jouons par �quipe */
1185 if (statut_joueurs->team == (statut_joueurs + 1)->team) {
1186 partenaire = ((num_bot) / 2) * 2 + 1 - (num_bot % 2);
1187 /* Si mon partenaire est mort */
1188 if ((statut_joueurs + partenaire)->lives == 0) {
1189 for (joueur = 0; joueur < nb_joueurs; joueur += 2)
1190 /* Si les deux joueurs d'une autre �quipe sont encore vivants. */
1191 if (((statut_joueurs + joueur)->team != ps->team)
1192 && ((statut_joueurs + joueur)->lives > 0)
1193 && ((statut_joueurs + joueur + 1)->lives > 0))
1194 equipe_complete = XBTrue;
1195 /* S'il n'y a pas d'�quipe compl�te... je swappe ! */
1196 if (!equipe_complete)
1197 vote_swap = XBTrue;
1198 }
1199 }
1200 /* Je swappe si je suis coinc� entre 4 murs (et que l'on ne joue pas par �quipe) */
1201 else if (ps->teleport == 0 && test_murs (ps) == 4)
1202 vote_swap = XBTrue;
1203
1204 /* Je swappe si je vais mourir */
1205 if (ps->dying || perf <= duree_deplacement)
1206 vote_swap = XBTrue;
1207
1208 return vote_swap;
1209 }
1210
1211 void
actions(BMPlayer * ps)1212 actions (BMPlayer * ps)
1213 {
1214 int i;
1215 int dx = 0, dy = 0;
1216 static int olddx = 0, olddy = 0;
1217 int dir;
1218 int max_perf;
1219 int choix_dir, prec_choix_dir;
1220 int x, y;
1221 int duree_meche, portee_bombe, type_bombe;
1222
1223 x = ps->x / BLOCK_WIDTH;
1224 y = ps->y / BLOCK_HEIGHT + 1;
1225 portee_bombe = (ps->illness == IllMini) ? 1 : ps->range;
1226 type_bombe = BMTdefault;
1227 def_score_extra (ps);
1228
1229 /* Remplissage du tableau my_maze */
1230 init_laby_perf ();
1231
1232 /* Je cherche les cases les plus s�res, en partant dans toutes les directions */
1233 parcours_par_niveau (ps);
1234
1235 /* Choix de la meilleure direction */
1236 choix_direction (&choix_dir, &max_perf);
1237 prec_choix_dir = choix_dir;
1238
1239 /* Et si j'essayais de poser une tit' bombe ? */
1240 vote_poser = XBFalse;
1241 if (souhaite_poser_bombe (ps)) {
1242 /* Calcul de la dur�e de m�che */
1243 duree_meche = fuse_times[curBombTime];
1244 /* Calcul des effets de l'explosion de cette bombe */
1245 /* if (laby_perf[x][y] > duree_meche)
1246 laby_perf[x][y] = duree_meche;
1247 developpe_bombe (portee_bombe, x, y, type_bombe); */
1248 // init_laby_perf_pose (x, y, portee_bombe, duree_meche, type_bombe);
1249
1250 /* Je cherche les cases les plus s�res, en partant dans toutes les directions */
1251 parcours_par_niveau (ps);
1252 /* Est-ce que poser me laisse la vie sauve ? */
1253 for (dir = 0; dir < NB_DIR; dir++) {
1254 if (perf_max[dir] > 10 * LONG_FUSE || duree_meche < ps->invincible) {
1255 vote_poser = XBTrue;
1256 break;
1257 }
1258 // fprintf(stderr," perf_max %i ",perf_max[dir]);
1259
1260 }
1261 // fprintf(stderr," dest %i \n",10 * LONG_FUSE);
1262 /* Si oui, je pose... et choisis la direction de d�part */
1263 if (vote_poser) {
1264 choix_direction (&choix_dir, &max_perf);
1265 /* Je ne pose pas si j'ai d�cid� d'aller vers un bonus (risque de mourir) */
1266 /* Remarque : m�thode provisoire � am�liorer... */
1267 if (dirige_vers_bonus (x, y, choix_dir)) {
1268 // fprintf(stderr, " go for bonus!\n");
1269
1270 vote_poser = XBFalse;
1271 // choix_dir = prec_choix_dir;
1272 }
1273 /*je ne pose pas si il ny a place pour ca (Skywalker) */
1274 if (!(ps->remote_control > 0)) {
1275 i = 1;
1276 dx = 1;
1277 conversion_direction (choix_dir, &dx, &dy);
1278 if (!CheckBomb (x - olddx, y - olddy))
1279 i = 0;
1280 /* pas verifier si ma position est libre */
1281
1282 if (dx - 1 != 0 && dy != 0)
1283 if ( //CheckBomb (x-olddx, y-olddy)&&
1284 CheckMazeFree2 (x + dx - 1, y + dy) && !CheckBomb (x + dx - 1, y + dy)) {
1285 i = 0;
1286 }
1287
1288 if (dx != 0 && dy + 1 != 0)
1289 if ( //CheckBomb (x-olddx, y-olddy)&&
1290 CheckMazeFree2 (x + dx, y + dy + 1) && !CheckBomb (x + dx, y + dy + 1)) {
1291 i = 0;
1292 }
1293 if (dx != 0 && dy - 1 != 0)
1294 if ( //CheckBomb (x-olddx, y-olddy)&&
1295 CheckMazeFree2 (x + dx, y + dy - 1) && !CheckBomb (x + dx, y + dy - 1)) {
1296 i = 0;
1297 }
1298 if (dx + 1 != 0 && dy != 0)
1299 /* verifier si il y a place pour escape de la bomb posee */
1300 if ( //CheckBomb (x-olddx, y-olddy)&&
1301 CheckMazeFree2 (x + dx + 1, y + dy) && !CheckBomb (x + dx + 1, y + dy)) {
1302 i = 0;
1303 }
1304
1305 if (i) {
1306 vote_poser = XBFalse;
1307 }
1308 if (olddx == -dx && olddy == -dy) {
1309 vote_poser = XBFalse;
1310 }
1311 if (ps->invincible > 5 && ps->remote_control > 0) {
1312 vote_poser = XBTrue;
1313 }
1314 }
1315 // if(
1316 }
1317 }
1318
1319 /* Si je vais mourir, j'essaie de toute fa�on de poser et de changer de case. */
1320 if (max_perf <= 30) {
1321 vote[STOP] -= 300;
1322 vote_poser = XBTrue;
1323 }
1324
1325 /* Est-ce que j'effectue une action sp�ciale ? */
1326 vote_action_speciale = XBFalse;
1327
1328 /* Si j'ai la t�l�commande (biscotte pour les intimes) */
1329 if (ps->remote_control > 0 && (max_perf > 10 * LONG_FUSE || ps->invincible > 5))
1330 if (test_biscotte (ps)) {
1331 vote_action_speciale = XBTrue;
1332 choix_dir = STOP;
1333 vote_poser = XBFalse;
1334 }
1335 /* Si je peux morpher, je morphe */
1336 if (ps->num_morph > 0) {
1337 vote_action_speciale = XBTrue;
1338 }
1339 /* Si je peux me t�l�porter et que je risque de mourir */
1340 if (ps->teleport > 0 && max_perf < 50) {
1341 vote_action_speciale = XBTrue;
1342 choix_dir = STOP;
1343 vote_poser = XBFalse;
1344 }
1345
1346 /* Si j'ai des bombes sp�ciales */
1347 if (ps->special_bombs > 0) {
1348 /* Si ce sont des bombes explosant imm�diatement
1349 if (get_current_level ()->bomb.buttonBMT == BMTblastnow)
1350 algo simpliste � modifier
1351 if (vote_poser && ps->invincible > 5)
1352 {
1353 vote_action_speciale = XBTrue;
1354 vote_poser = XBFalse;
1355 } */
1356 }
1357 /* Ai-je envie de swapper ? */
1358 vote_swap = XBFalse;
1359 /* if (ps->swapper > 0 && test_swap (ps, max_perf))
1360 vote_swap = XBTrue; */
1361
1362 vote[choix_dir] += 200;
1363 olddy = dy;
1364 olddx = dx;
1365 }
1366
1367 /* Inversion des directions */
1368 int
inversion(int dir)1369 inversion (int dir)
1370 {
1371 switch (dir) {
1372 case UP:
1373 return DOWN;
1374 case DOWN:
1375 return UP;
1376 case LEFT:
1377 return RIGHT;
1378 case RIGHT:
1379 return LEFT;
1380 default:
1381 return dir;
1382 }
1383 }
1384
1385 /* Mouvement � faire si je suis coinc� entre deux cases */
1386 int
decoince(int dir)1387 decoince (int dir)
1388 {
1389 static int compteur = 0;
1390 int nouv_dir = GoDefault;
1391
1392 /* Pour �viter de gigoter entre 2 bombes */
1393 compteur++;
1394 if (compteur > 4) {
1395 compteur = 0;
1396 nouv_dir = dir;
1397 }
1398
1399 return nouv_dir;
1400 }
1401
1402 /* Retourne VRAI si je peux tuer des ennemis */
1403 int
repose_en_mourant(BMPlayer * ps)1404 repose_en_mourant (BMPlayer * ps)
1405 {
1406 int mazex, mazey;
1407 int portee_bombe;
1408
1409 mazex = (int)(ps->x + 0.5 * BLOCK_WIDTH) / BLOCK_WIDTH;
1410 mazey = (int)(ps->y + 0.5 * BLOCK_HEIGHT) / BLOCK_HEIGHT + 1;
1411 portee_bombe = (ps->illness == IllMini) ? 1 : ps->range;
1412
1413 if (score_tue (mazex, mazey, portee_bombe) >= 0 && nb_ennemis_vivants > 0)
1414 return XBTrue;
1415 else
1416 return XBFalse;
1417 }
1418
1419 void
gestionBot(BMPlayer * player_stat,PlayerAction * player_action,int numero_bot,int num_player)1420 gestionBot (BMPlayer * player_stat, PlayerAction * player_action, int numero_bot, int num_player)
1421 {
1422 int i, j;
1423 int max = MALUS_MORT;
1424 int choice = -1;
1425 int mazex, mazey;
1426 int inverse;
1427 BMPlayer *ps;
1428 PlayerAction *pa;
1429 /* Fouf lenteur -- *//* trace = 0; */
1430
1431 /* Fouf lenteur ++ *//* fprintf(stderr, "gestionBot\n"); */
1432 /* Fouf lenteur ++ *//* fflush(stderr); */
1433
1434 ps = player_stat + numero_bot;
1435 pa = player_action + numero_bot;
1436 statut_joueurs = player_stat;
1437 num_bot = numero_bot;
1438 nb_joueurs = num_player;
1439
1440 mazex = ps->x / BLOCK_WIDTH;
1441 mazey = ps->y / BLOCK_HEIGHT + 1;
1442
1443 /* Suis-je rapide ? */
1444 if (ps->illness == IllRun)
1445 duree_deplacement = FAST_SPEED;
1446 else /* Suis-je Lent ? */ if (ps->illness == IllSlow)
1447 duree_deplacement = SLOW_SPEED;
1448 else
1449 duree_deplacement = NORMAL_SPEED;
1450
1451 temps_jeu = gameTime;
1452 /* D�but d'un niveau */
1453 if (temps_jeu == 1)
1454 init_laby_shrink ();
1455
1456 /* Suis-je invers� ? */
1457 if (ps->illness == IllReverse)
1458 inverse = XBTrue;
1459 else
1460 inverse = XBFalse;
1461
1462 /* Si je me trouve entre deux cases */
1463 /* Fouf lenteur -- *//* if ((ps->x % BLOCK_WIDTH) != 0 || (ps->y % BLOCK_HEIGHT) != 0) */
1464 /* Fouf lenteur ++ */ if (((ps->x % BLOCK_WIDTH) != 0 || (ps->y % BLOCK_HEIGHT) != 0)
1465 || ((ps->d_ist == GoStop) && (temps_jeu % 3))) {
1466 switch (ps->d_ist) {
1467 case GoUp:
1468 /* kick si est possible */
1469 if (CheckBomb (mazex, mazey) && !(ps->kick && CheckMazeFree2 (mazex, mazey - 1)))
1470 pa->dir = decoince (GoDown);
1471 break;
1472 case GoDown:
1473 if (CheckBomb (mazex, mazey + 1) && !(ps->kick && CheckMazeFree2 (mazex, mazey + 2)))
1474 pa->dir = decoince (GoUp);
1475 break;
1476 case GoLeft:
1477 if (CheckBomb (mazex, mazey) && !(ps->kick && CheckMazeFree2 (mazex - 1, mazey)))
1478 pa->dir = decoince (GoRight);
1479 break;
1480 case GoRight:
1481 if (CheckBomb (mazex + 1, mazey) && !(ps->kick && CheckMazeFree2 (mazex + 2, mazey)))
1482 pa->dir = decoince (GoLeft);
1483 break;
1484 default:
1485 break;
1486 }
1487 /* Si je meurs, je pose */
1488 if (ps->dying)
1489 pa->bomb = repose_en_mourant (ps);
1490 if (inverse)
1491 pa->dir = inversion (pa->dir);
1492 return;
1493 }
1494
1495 if (pa->dir == GoStop && !(temps_jeu & 1))
1496 return;
1497
1498 /* Initialisation */
1499 for (i = 0; i < NB_DIR; i++)
1500 vote[i] = 0;
1501
1502 test_murs (ps); /* Don't walk into walls ... */
1503
1504 /* Choix de la bonne direction et des actions � effectuer */
1505 actions (ps);
1506
1507 /* getBonuses (ps);
1508 putBombs (ps); break the walls ... */
1509 /* randChoice (); */
1510
1511 for (j = 0; j < NB_DIR; j++)
1512 if (vote[j] > max) {
1513 /* Fouf lenteur -- *//* if (trace) printf ("Ok for %d %d\n", j, vote[j]); */
1514 max = vote[j];
1515 choice = j;
1516 }
1517 /* Fouf lenteur -- *//* else */
1518 /* Fouf lenteur -- *//* if (trace) printf ("Not ok for %d %d\n", j, vote[j]); */
1519
1520 switch (choice) {
1521 case STOP:
1522 /* Fouf lenteur -- *//* pa->dir = GoStop; */
1523 /* Fouf lenteur ++ */ if (ps->d_ist == GoStop) {
1524 /* Fouf lenteur ++ */ pa->dir = GoDefault;
1525 /* Fouf lenteur ++ *//* fprintf(stderr, "GoDefault (already stop)\n"); */
1526 /* Fouf lenteur ++ */ }
1527 else {
1528 /* Fouf lenteur ++ */ pa->dir = GoStop;
1529 /* Fouf lenteur ++ *//* fprintf(stderr, "GoStop (stop NOW *********)\n"); */
1530 /* Fouf lenteur ++ */ }
1531 break;
1532 case UP:
1533 pa->dir = GoUp;
1534 /* Fouf lenteur ++ *//* fprintf(stderr, "GoUp\n"); */
1535 break;
1536 case LEFT:
1537 pa->dir = GoLeft;
1538 /* Fouf lenteur ++ *//* fprintf(stderr, "GoLeft\n"); */
1539 break;
1540 case DOWN:
1541 pa->dir = GoDown;
1542 /* Fouf lenteur ++ *//* fprintf(stderr, "GoDown\n"); */
1543 break;
1544 case RIGHT:
1545 pa->dir = GoRight;
1546 /* Fouf lenteur ++ *//* fprintf(stderr, "GoRight\n"); */
1547 break;
1548 }
1549 /* Fouf lenteur ++ *//* fflush(stderr); */
1550
1551 /* Ai-je d�cid� de poser ? */
1552 if (vote_poser)
1553 pa->bomb = XBTrue;
1554
1555 /* Ai-je d�cid� de faire une action sp�ciale ? */
1556 if (vote_action_speciale)
1557 pa->special = XBTrue;
1558
1559 /* Ai-je envie de swapper ?
1560 if (vote_swap)
1561 pa->swap = XBTrue; */
1562
1563 if (inverse)
1564 pa->dir = inversion (pa->dir);
1565 }
1566
1567 /* BMFuncData :
1568 special_init : bonus EXTRA au d�part
1569 special_game : jeu sp�cial (bombes hant�es, lanc�es par les murs, ...)
1570 special_extra : bonus EXTRA � trouver
1571 special_key : action du +
1572 */
1573