// Obstacle.cpp // #include "DECOR.H" #include "MISC.H" #include "ACTION.H" // Cette table indique les obstacles sur les sols. // 0=passage, 1=obstacle static char tableObstacleFloor[] = { 1,1,1,1,1, // 0 (noir pour limites) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, // 1 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,1,1,1, // 2 0,1,1,1,1, 0,1,1,1,1, 0,1,1,1,1, 0,1,1,1,1, 0,0,0,0,0, // 3 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, // 4 1,1,1,1,0, 1,1,1,1,0, 1,1,1,1,0, 1,1,1,1,0, 1,1,1,1,1, // 5 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,0,0,0,0, // 6 0,0,1,1,1, 0,1,1,1,1, 0,1,1,1,1, 0,1,1,1,1, 0,0,0,0,0, // 7 1,1,1,0,0, 1,1,1,1,0, 1,1,1,1,0, 1,1,1,1,0, 1,1,1,1,0, // 8 1,1,1,1,0, 1,1,1,1,0, 1,1,1,0,0, 0,0,0,0,0, 0,1,1,1,1, // 9 0,1,1,1,1, 0,1,1,1,1, 0,0,1,1,1, 0,0,0,0,0, 0,0,1,1,1, // 10 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, // 11 1,1,1,1,0, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 12 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,1,1,0,0, 1,1,1,1,1, // 13 1,1,1,1,1, 1,1,1,1,1, 0,1,1,1,1, 0,0,1,1,1, 1,1,1,1,1, // 14 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, // 15 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 16 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 17 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 18 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 19 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 20 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 21 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 22 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 23 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 24 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 25 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 26 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 27 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 28 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 29 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 30 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 31 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 32 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 33 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 34 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 35 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 36 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 37 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 38 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 39 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 40 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 41 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 42 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 43 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 44 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 45 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 46 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 47 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 48 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 49 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 50 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 51 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 52 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 53 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 54 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 55 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 56 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 57 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 58 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 59 (pont e-o) 0,0,0,0,0, 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, // 60 0,0,0,0,0, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, // 61 0,0,0,0,0, 1,1,1,1,0, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, // 62 (pont n-s) 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, // 63 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, // 64 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,1,1, }; // Cette table indique les obstacles sur les sols pour le bateau. // 0=passage, 1=obstacle static char tableObstacleFloorBateau[] = { 1,1,1,1,1, // 2 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 3 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,1,1,1, // 4 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 5 0,0,0,0,0, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 6 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 7 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,1,1,1, // 8 0,0,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 9 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, // 10 1,1,1,0,0, 1,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,1, // 11 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 12 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 13 0,0,0,0,0, 1,1,1,0,0, 1,1,1,0,0, 1,1,1,0,0, 0,0,0,0,0, // 14 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, }; // Cette table indique les obstacles sur les objets. // 0=passage, 1=obstacle static char tableObstacleObject[] = { 0,0,0,0,0, // 0 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 1 0,1,0,0,0, 0,1,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 2 0,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 3 0,1,1,1,0, 0,1,1,1,0, 0,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, // 4 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 1,1,1,1,1, // 5 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, // 6 (arbre) 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 7 0,0,0,0,0, 0,0,0,1,0, 0,0,1,1,1, 0,0,0,1,0, 0,0,0,0,0, // 8 0,1,0,0,0, 0,1,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 9 0,0,0,1,0, 0,0,1,1,0, 0,1,1,1,0, 0,0,0,0,0, 0,1,1,1,1, // 10 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,1,1,0, 1,1,1,1,0, // 11 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,1,1,1, 0,1,1,1,0, // 12 (fus�e) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,1,1,0, 0,0,0,0,0, // 13 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 14 (m�tal) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 1,1,1,1,1, // 15 (maison construction) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, // 16 (armure) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 1,1,1,1,1, // 17 (batiment ennemi) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 18 1,1,1,1,1, 1,1,1,1,1, 1,0,0,0,0, 1,1,1,1,1, 0,0,0,0,0, // 19 (�lectro pi�g�) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 1,1,1,1,1, // 20 (mur) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 21 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 22 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 23 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 24 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 25 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 26 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 27 (tour) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 28 (laboratoire) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, 1,1,1,1,1, // 1,1,1,1,1, // 28 (laboratoire) // 1,1,1,1,1, // 1,1,1,1,1, // 1,1,1,1,1, // 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, // 30 (arbre sans feuilles) 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 31 0,0,0,0,0, 0,0,0,1,0, 0,0,1,1,1, 0,0,0,1,0, 0,0,0,0,0, // 32 0,1,0,0,0, 0,1,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 33 0,0,0,1,0, 0,0,1,1,0, 0,1,1,1,0, 0,0,0,0,0, 0,1,1,1,1, // 34 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,1,1,0, 1,1,1,1,0, // 35 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,1,1,1, 0,0,0,0,0, // 36 (tas de planches) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 1,1,1,1,1, // 37 (rochers) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 38 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 39 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 40 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 41 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 42 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 43 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 44 (tas de pierres) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 45 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 46 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 47 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 48 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 49 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 50 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 51 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 52 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 53 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 54 0,0,0,0,0, 1,1,1,0,0, 1,1,1,0,0, 1,1,1,0,0, 1,1,1,0,0, // 55 1,1,1,0,0, 1,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,1, // 56 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 57 (plante) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 58 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 59 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 60 (tomates) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 1,1,1,1,1, // 61 (cabane) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 62 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, // 63 (oeufs) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 1,1,1,1,1, // 64 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, // 65 (palissade) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, 0,1,1,0,0, 1,1,1,1,0, // 66 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, 0,1,1,0,0, 1,1,1,1,0, // 67 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, 0,1,1,0,0, 1,1,1,1,0, // 68 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, 0,1,1,0,0, 1,1,1,1,0, // 69 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, 0,1,1,0,0, 1,1,1,1,0, // 70 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, 0,1,1,0,0, 1,1,1,1,0, // 71 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, 0,1,1,0,0, 0,0,0,0,0, // 72 (pont en construction) 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 73 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 74 (rayon tour) 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 75 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 76 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 77 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 78 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 79 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 80 (bouteille) 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,1,1,1,0, // 81 (fleurs) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,1,1,0, 0,0,0,0,0, // 82 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,1,1,1,0, // 83 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,1,1,0, 0,0,0,0,0, // 84 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 85 (dynamite) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 86 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 87 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 88 (explosion) 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 89 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 90 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 91 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 92 (poison) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 93 (pi�ge) 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,1,1,1,0, // 94 (fleurs) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,1,1,0, 0,0,0,0,0, // 95 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 96 (araign�e dans pi�ge) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 97 (tracks dans pi�ge) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 98 (robot dans pi�ge) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 1,1,1,1,1, // 99 (recharge) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, 1,1,1,0,0, 1,1,1,1,1, // 100 (batiment ennemi) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 101 1,1,1,1,1, 1,1,1,1,1, 1,0,0,0,0, 1,1,1,1,1, 1,1,1,1,1, // 102 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 103 1,1,1,1,1, 1,1,1,1,1, 1,0,0,0,0, 1,1,1,1,1, 1,1,1,1,1, // 104 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 105 1,1,1,1,1, 1,1,1,1,1, 1,0,0,0,0, 1,1,1,1,1, 1,1,1,1,1, // 106 (barri�re) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 107 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 108 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 109 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 110 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 111 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 112 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 113 (maison) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, 1,1,1,1,1, 0,0,0,0,0, // 114 (bombe dans pi�ge) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 1,1,1,1,1, // 115 (batiment ennemi) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 116 1,1,1,1,1, 1,1,1,1,1, 1,0,0,0,0, 1,1,1,1,1, 0,0,0,0,0, // 117 (bateau) 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 118 (jeep) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 1,1,1,1,1, // 119 (usine) 1,1,1,1,1, 1,1,1,1,1, 1,0,0,0,1, 1,1,1,1,1, 1,1,1,1,1, // 120 1,1,1,1,1, 1,1,1,1,1, 1,0,0,0,0, 1,1,1,1,1, 1,1,1,1,1, // 121 (mine de fer) 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, // 122 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0, 1,1,1,1,1, 0,0,0,0,0, // 123 (fer) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 124 (drapeau) 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 125 (mine) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, 0,0,0,0,0, // 126 (mine de fer, �chaffaudage) 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, // 127 (mine) 0,0,0,0,0, 0,0,1,1,1, 0,0,1,1,1, 0,0,1,1,1, }; // Retourne les obstacles autour d'une cellule, sous la // forme d'un tableau de 3x3. void CDecor::SearchFloor(int rank, int icon, POINT cel, int *pBits) { char* pTable; int first, last; int dx, dy, x, y, i; int def = 0; pTable = tableObstacleFloor; first = 0; last = 64; if ( rank != -1 && m_blupi[rank].vehicule == 1 ) // en bateau ? { pTable = tableObstacleFloorBateau; first = 2; last = 14; def = 1; } if ( icon >= first && icon <= last ) { pTable += (icon-first)*5*5; if ( cel.x%2 == 0 ) dx = 0; else dx = 2; if ( cel.y%2 == 0 ) dy = 0; else dy = 2; for ( y=dy ; y<dy+3 ; y++ ) { for ( x=dx ; x<dx+3 ; x++ ) { *pBits++ = pTable[x+y*5]; } } } else { for ( i=0 ; i<9 ; i++ ) { *pBits++ = def; } } } // Retourne les obstacles autour d'une cellule, sous la // forme d'un tableau de 3x3. void CDecor::SearchObject(int rank, int icon, POINT cel, int *pBits) { char* pTable; int dx, dy, x, y, i; if ( icon >= 0 && icon <= 127 ) { pTable = tableObstacleObject+(icon)*5*5; if ( cel.x%2 == 0 ) dx = 0; else dx = 2; if ( cel.y%2 == 0 ) dy = 0; else dy = 2; for ( y=dy ; y<dy+3 ; y++ ) { for ( x=dx ; x<dx+3 ; x++ ) { *pBits++ = pTable[x+y*5]; } } } else { for ( i=0 ; i<9 ; i++ ) { *pBits++ = 0; } } } // Ajuste un sol en fonction du personnage. void CDecor::AjustFloor(int rank, int icon, POINT cel, int *pBits) { int i; if ( rank < 0 ) return; if ( m_blupi[rank].perso == 0 ) // blupi ? { if ( m_blupi[rank].interrupt == -1 ) // passe muraille (*) ? { goto pass; } if ( m_blupi[rank].vehicule == 1 ) // en bateau ? { if ( icon >= 59 && icon <= 64 ) goto lock; // pont ? } return; } if ( m_blupi[rank].perso == 2 ) // virus ? { goto pass; // le virus peut aller partout (il volle) return; } if ( m_blupi[rank].perso == 3 ) // tracks ? { if ( icon >= 59 && icon <= 64 ) // ponts ? { goto lock; // le tracks ne peut pas aller sur les ponts } return; } //- if ( m_blupi[rank].perso == 4 ) // robot ? //- { //- if ( icon >= 59 && icon <= 64 ) // ponts ? //- { //- goto lock; // le robot ne peut pas aller sur les ponts //- } //- return; //- } return; pass: for ( i=0 ; i<9 ; i++ ) { *pBits++ = 0; // peut passer } return; lock: for ( i=0 ; i<9 ; i++ ) { *pBits++ = 1; // bloqu� } return; } // (*) Blupi est passe muraille lorsqu'il embarque ou d�barque // du bateau. Dans ce cas, tous les sols (rivages) doivent // permettre de passer. En revanche, pas les obstacles ! // Ajuste un obstacle en fonction du personnage. void CDecor::AjustObject(int rank, int icon, POINT cel, int *pBits) { int i; if ( rank < 0 ) return; if ( m_blupi[rank].perso == 0 ) // blupi ? { if ( m_blupi[rank].vehicule != 0 && // pas � pied ? cel.x%2 == 1 && cel.y%2 == 1 && m_decor[cel.x/2][cel.y/2].objectIcon == 117 ) // bateau ? { goto lock; // blupi ne peut pas aller dans le bateau } // if ( m_blupi[rank].interrupt == -1 ) // passe muraille (*) ? // { // goto pass; // } // if ( cel.x > 0 && cel.x%2 == 0 && cel.y%2 == 1 && // (m_decor[(cel.x-2)/2][cel.y/2].objectIcon == 100 || // usine ? // m_decor[(cel.x-2)/2][cel.y/2].objectIcon == 102 || // m_decor[(cel.x-2)/2][cel.y/2].objectIcon == 104 || // m_decor[(cel.x-2)/2][cel.y/2].objectIcon == 115 || // m_decor[(cel.x-2)/2][cel.y/2].objectIcon == 17) ) // { // goto lock; // blupi ne peut pas bloquer la porte // } if ( cel.x%2 == 1 && cel.y%2 == 1 && m_decor[cel.x/2][cel.y/2].objectIcon == 99 ) // recharge ? { goto lock; // blupi ne peut pas bloquer la station } if ( m_blupi[rank].vehicule == 2 && // en jeep ? m_decor[cel.x/2][cel.y/2].objectIcon == 113 ) // maison ? { goto lock; // blupi ne peut pas aller dans la maison } return; } if ( m_blupi[rank].perso == 1 ) // araign�e ? { // if ( cel.x%2 != 0 && cel.y%2 != 0 && if ( IsSpiderObject(icon) ) // tomate ou poison ? { goto pass; // l'araign�e peut aller dans les tomates } return; } if ( m_blupi[rank].perso == 2 ) // virus ? { if ( icon == 81 || icon == 83 || icon == 94 || // fleurs non-coup�es ? (icon >= 106 && icon <= 112) ) // barri�res ennemies ? { goto pass; // le virus peut aller } return; } if ( m_blupi[rank].perso == 3 ) // tracks ? { if ( IsTracksObject(icon) ) // fleurs ou objet ? { goto pass; // le tracks peut aller } if ( icon == 113 || // maison ? icon == 28 || icon == 29 || // laboratoire ? icon == 119 || icon == 120 || // usine ? icon == 121 || icon == 122 ) // mine de fer ? { goto lock; // le tracks ne peut pas aller dans la maison } return; } if ( m_blupi[rank].perso == 4 ) // robot ? { if ( IsRobotObject(icon) ) // pi�ge ou dynamite ? { goto pass; // le robot peut aller } return; } if ( m_blupi[rank].perso == 5 ) // bombe ? { if ( icon == 93 ) // pi�ge ? { goto pass; // la bombe peut aller } return; } if ( m_blupi[rank].perso == 7 ) // �lectro ? { if ( icon == 93 ) // pi�ge ? { goto pass; // l'�lectro peut aller } if ( icon == 113 || // maison ? icon == 28 || icon == 29 || // laboratoire ? icon == 119 || icon == 120 || // usine ? icon == 121 || icon == 122 ) // mine de fer ? { goto lock; // l'�lectro ne peut pas aller dans la maison } return; } if ( m_blupi[rank].perso == 8 ) // disciple ? { if ( cel.x > 0 && cel.x%2 == 0 && cel.y%2 == 1 && (m_decor[(cel.x-2)/2][cel.y/2].objectIcon == 100 || // usine ? m_decor[(cel.x-2)/2][cel.y/2].objectIcon == 102 || m_decor[(cel.x-2)/2][cel.y/2].objectIcon == 104 || m_decor[(cel.x-2)/2][cel.y/2].objectIcon == 115) ) { goto lock; // disciple ne peut pas bloquer la porte } if ( cel.x%2 == 1 && cel.y%2 == 1 && m_decor[cel.x/2][cel.y/2].objectIcon == 99 ) // recharge ? { goto lock; // disciple ne peut pas bloquer la station } if ( m_decor[cel.x/2][cel.y/2].objectIcon == 113 ) // maison ? { goto lock; // disciple ne peut pas aller dans la maison } return; } return; pass: for ( i=0 ; i<9 ; i++ ) { *pBits++ = 0; // peut passer } return; lock: for ( i=0 ; i<9 ; i++ ) { *pBits++ = 1; // bloqu� } return; } // Copie un tableau 3x3 dans un tableau 9x9. void Copy33To99(int *pSrc33, int *pDst99, int dx, int dy) { int x, y; for ( y=0 ; y<3 ; y++ ) { for ( x=0 ; x<3 ; x++ ) { pDst99[(dx+1)*3+x + ((dy+1)*3+y)*9] = pSrc33[x+y*3]; } } } // Indique s'il est possible d'avancer dans une direction donn�e. bool CDecor::IsFreeDirect(POINT cel, int direct, int rank) { int icon, workBlupi; int bits[3*3], obstacles[9*9]; POINT test, vector; vector = GetVector(direct); test.x = cel.x+vector.x; test.y = cel.y+vector.y; if ( m_decor[test.x/2][test.y/2].fire > 0 && m_decor[test.x/2][test.y/2].fire < MoveMaxFire() ) return false; // Cellule bloqu�e (un blupi travaille ici) ? if ( m_blupi[rank].perso != 3 ) // pas tracks ? { workBlupi = m_decor[test.x/2][test.y/2].workBlupi; if ( workBlupi >= 0 && workBlupi != rank ) return false; } // D�placement possible par-rapport au sol ? // icon = m_decor[cel.x/2][cel.y/2].floorIcon; // SearchFloor(rank, icon, cel, bits); // AjustFloor(rank, icon, cel, bits); // if ( bits[(1+vector.x)+(1+vector.y)*3] == 1 ) return false; icon = m_decor[test.x/2][test.y/2].floorIcon; SearchFloor(rank, icon, test, bits); AjustFloor(rank, icon, test, bits); if ( bits[1+1*3] == 1 ) return false; if ( bits[(1-vector.x)+(1-vector.y)*3] == 1 ) return false; // D�placement possible par-rapport aux obstacles ? icon = m_decor[cel.x/2][cel.y/2].objectIcon; SearchObject(rank, icon, cel, bits); AjustObject(rank, icon, cel, bits); if ( bits[(1+vector.x)+(1+vector.y)*3] == 1 ) return false; icon = m_decor[test.x/2][test.y/2].objectIcon; SearchObject(rank, icon, test, bits); AjustObject(rank, icon, test, bits); if ( bits[(1-vector.x)+(1-vector.y)*3] == 1 ) return false; if ( bits[1+1*3] == 1 ) return false; if ( vector.x != 0 && vector.y != 0 ) // d�placement diagonal ? { test.x = cel.x; test.y = cel.y+vector.y; icon = m_decor[test.x/2][test.y/2].objectIcon; SearchObject(rank, icon, test, bits); AjustObject(rank, icon, test, bits); Copy33To99(bits, obstacles, 0, vector.y); test.x = cel.x+vector.x; test.y = cel.y; icon = m_decor[test.x/2][test.y/2].objectIcon; SearchObject(rank, icon, test, bits); AjustObject(rank, icon, test, bits); Copy33To99(bits, obstacles, vector.x, 0); if ( obstacles[(4+vector.x*1)+(4+vector.y*2)*9] == 1 ) return false; if ( obstacles[(4+vector.x*2)+(4+vector.y*1)*9] == 1 ) return false; } return true; // pas d'obstacle } // Indique si une cellule contient un objet. // Est utilis� lors du dessin (BuildPutBlupi), pour savoir // si blupi est devant un objet. bool CDecor::IsFreeCelObstacle(POINT cel) { int icon; int bits[9]; if ( !IsValid(cel) ) return false; if ( m_decor[cel.x/2][cel.y/2].fire > 0 && m_decor[cel.x/2][cel.y/2].fire < MoveMaxFire() ) return false; icon = m_decor[cel.x/2][cel.y/2].objectIcon; if ( icon != -1 ) { SearchObject(-1, icon, cel, bits); if ( bits[1+1*3] == 1 ) return false; } return true; // pas d'obstacle } // Indique si une cellule contient un sol. // Est utilis� pour savoir si blupi peut aller sur une cellule // en tenant compte uniquement des sols. // Retourne true si blupi peut y aller ! bool CDecor::IsFreeCelFloor(POINT cel, int rank) { int icon; int bits[9]; if ( !IsValid(cel) ) return false; icon = m_decor[cel.x/2][cel.y/2].floorIcon; if ( icon != -1 ) { SearchFloor(rank, icon, cel, bits); AjustFloor(rank, icon, cel, bits); if ( bits[1+1*3] == 1 ) return false; } return true; // pas d'obstacle } // Indique si une cellule est libre. // Est utilis� pour savoir si blupi peut venir ici // d�barquer en bateau ou monter dans sa jeep. bool CDecor::IsFreeCelGo(POINT cel, int rank) { bool bOK; POINT limit; int action, channel, icon; if ( rank == -1 ) return IsFreeCel(cel, rank); GetObject(cel, channel, icon); // Refuse d'aller dans la maison si blupi porte qq chose. if ( m_blupi[rank].takeChannel != -1 && // porte qq chose ? channel == CHOBJECT && icon == 113 ) // maison ? { return false; } // Refuse d'aller dans le laboratoire (on peut seulement // y transformer qq chose). if ( channel == CHOBJECT && (icon == 28 || // laboratoire ? icon == 120 || // usine ? icon == 122) ) // mine de fer ? { return false; } bOK = IsFreeCel(cel, rank); if ( bOK ) return true; bOK = IsFreeCelEmbarque(cel, rank, action, limit); if ( bOK ) return true; bOK = IsFreeCelDebarque(cel, rank, action, limit); if ( bOK ) return true; if ( !m_blupi[rank].bMalade && m_blupi[rank].vehicule == 0 && // � pied ? m_blupi[rank].perso != 8 && // pas le disciple ? channel == CHOBJECT && icon == 118 ) // jeep ? { return true; } if ( !m_blupi[rank].bMalade && m_blupi[rank].vehicule == 0 && // � pied ? m_blupi[rank].perso != 8 && // pas le disciple ? m_blupi[rank].energy > MAXENERGY/4 && // fort ? m_blupi[rank].takeChannel == -1 && // porte rien ? channel == CHOBJECT && icon == 16 ) // armure ? { return true; } return false; } // Indique si on peut faire qq chose sur une cellule. // Est utilis� pour savoir comment est la mise en �vidence (hili) // � cet endroit. bool CDecor::IsFreeCelHili(POINT cel, int rank) { bool bOK; POINT limit; int workBlupi, channel, icon, action; if ( IsValid(cel) ) { workBlupi = m_decor[cel.x/2][cel.y/2].workBlupi; if ( workBlupi >= 0 && workBlupi != rank ) return false; channel = m_decor[cel.x/2][cel.y/2].objectChannel; icon = m_decor[cel.x/2][cel.y/2].objectIcon; if ( channel == CHOBJECT && (icon == 12 || // fus�e ? (icon >= 20 && icon <= 26) || // mur ? (icon >= 106 && icon <= 112) || // barri�re ? (icon >= 99 && icon <= 105) || // batiment ennemi ? (icon >= 115 && icon <= 116) || // idem ? (icon >= 17 && icon <= 18)) ) // idem ? { return false; } } if ( rank == -1 ) return IsFreeCelFloor(cel, rank); bOK = IsFreeCelFloor(cel, rank); if ( bOK ) return true; bOK = IsFreeCelEmbarque(cel, rank, action, limit); if ( bOK ) return true; bOK = IsFreeCelDebarque(cel, rank, action, limit); if ( bOK ) return true; return false; } // Indique si une cellule est libre. // Est utilis� pour savoir si blupi peut venir ici. bool CDecor::IsFreeCel(POINT cel, int rank) { int icon, workBlupi; int bits[9]; if ( !IsValid(cel) ) return false; if ( m_decor[cel.x/2][cel.y/2].fire > 0 && m_decor[cel.x/2][cel.y/2].fire < MoveMaxFire() ) return false; // Cellule bloqu�e (un blupi travaille ici) ? if ( rank != -1 && m_blupi[rank].perso != 3 ) // pas tracks ? { workBlupi = m_decor[cel.x/2][cel.y/2].workBlupi; if ( workBlupi >= 0 && workBlupi != rank ) return false; } icon = m_decor[cel.x/2][cel.y/2].floorIcon; SearchFloor(rank, icon, cel, bits); AjustFloor(rank, icon, cel, bits); if ( bits[1+1*3] == 1 ) return false; icon = m_decor[cel.x/2][cel.y/2].objectIcon; SearchObject(rank, icon, cel, bits); AjustObject(rank, icon, cel, bits); if ( bits[1+1*3] == 1 ) return false; return true; // pas d'obstacle } // Indique si blupi peut d�poser un objet ici. bool CDecor::IsFreeCelDepose(POINT cel, int rank) { int icon; if ( !IsFreeCel(cel, rank) ) return false; icon = m_decor[cel.x/2][cel.y/2].objectIcon; if ( icon == 10000 || icon == 10001 || // �clairs entre tours ? icon == 18 ) // dalle glissante ? { return false; } icon = m_decor[cel.x/2][cel.y/2].floorIcon; if ( icon == 80 ) // t�l�porteur ? { return false; } return true; } // Indique s'il est possible d'embarquer ici. // Le point retourn� dans "limit" indique jusqu'o� il est // possible de marcher normalement (sans passe muraille). bool CDecor::IsFreeCelEmbarque(POINT cel, int rank, int &action, POINT &limit) { bool bOK; int channel, icon; // Impossible si blupi n'est pas � pied, // ou s'il s'agit d'un disciple. if ( rank == -1 || m_blupi[rank].vehicule != 0 || m_blupi[rank].perso == 8 ) return false; // A-t-on cliqu� sur un bateau ? if ( cel.x%2 != 1 || cel.y%2 != 1 ) return false; GetObject(cel, channel, icon); if ( channel != CHOBJECT || icon != 117 ) return false; GetFloor(cel, channel, icon); if ( channel == CHFLOOR && icon == 2 ) { m_blupi[rank].vehicule = 1; bOK = IsFreeCel(GetCel(cel,+1,0), rank); // libre (en bateau) ? m_blupi[rank].vehicule = 0; if ( bOK ) { limit = GetCel(cel,-2,0); action = WM_ACTION_BATEAUDE; return true; } } GetFloor(cel, channel, icon); if ( channel == CHFLOOR && icon == 3 ) { m_blupi[rank].vehicule = 1; bOK = IsFreeCel(GetCel(cel,0,+1), rank); // libre (en bateau) ? m_blupi[rank].vehicule = 0; if ( bOK ) { limit = GetCel(cel,0,-2); action = WM_ACTION_BATEAUDS; return true; } } GetFloor(cel, channel, icon); if ( channel == CHFLOOR && icon == 4 ) { m_blupi[rank].vehicule = 1; bOK = IsFreeCel(GetCel(cel,-1,0), rank); // libre (en bateau) ? m_blupi[rank].vehicule = 0; if ( bOK ) { limit = GetCel(cel,+1,0); action = WM_ACTION_BATEAUDO; return true; } } GetFloor(cel, channel, icon); if ( channel == CHFLOOR && icon == 5 ) { m_blupi[rank].vehicule = 1; bOK = IsFreeCel(GetCel(cel,0,-1), rank); // libre (en bateau) ? m_blupi[rank].vehicule = 0; if ( bOK ) { limit = GetCel(cel,0,+1); action = WM_ACTION_BATEAUDN; return true; } } return false; } // Indique s'il est possible de d�barquer ici. // Le point retourn� dans "limit" indique jusqu'o� il est // possible de naviguer normalement (sans passe muraille). bool CDecor::IsFreeCelDebarque(POINT cel, int rank, int &action, POINT &limit) { bool bOK; int channel1, icon1; int channel2, icon2; // Impossible si blupi n'est pas en bateau. if ( rank == -1 || m_blupi[rank].vehicule != 1 ) return false; m_blupi[rank].vehicule = 0; bOK = IsFreeCel(cel, rank); // libre (� pied) ? m_blupi[rank].vehicule = 1; if ( !bOK ) return false; GetFloor(GetCel(cel,+2,0), channel1, icon1); GetObject(GetCel(cel,+2,0), channel2, icon2); if ( channel1 == CHFLOOR && icon1 == 2 && // rive ? channel2 == -1 && icon2 == -1 && // pas de bateau amarr� ? cel.x%2 == 1 && cel.y%2 == 1 ) { limit = GetCel(cel,+3,0); action = WM_ACTION_BATEAUAE; return true; } GetFloor(GetCel(cel,0,+2), channel1, icon1); GetObject(GetCel(cel,0,+2), channel2, icon2); if ( channel1 == CHFLOOR && icon1 == 3 && // rive ? channel2 == -1 && icon2 == -1 && // pas de bateau amarr� ? cel.x%2 == 1 && cel.y%2 == 1 ) { limit = GetCel(cel,0,+3); action = WM_ACTION_BATEAUAS; return true; } GetFloor(GetCel(cel,-2,0), channel1, icon1); GetObject(GetCel(cel,-2,0), channel2, icon2); if ( channel1 == CHFLOOR && icon1 == 4 && // rive ? channel2 == -1 && icon2 == -1 && // pas de bateau amarr� ? cel.x%2 == 0 && cel.y%2 == 1 ) { limit = GetCel(cel,-2,0); action = WM_ACTION_BATEAUAO; return true; } GetFloor(GetCel(cel,0,-2), channel1, icon1); GetObject(GetCel(cel,0,-2), channel2, icon2); if ( channel1 == CHFLOOR && icon1 == 5 && // rive ? channel2 == -1 && icon2 == -1 && // pas de bateau amarr� ? cel.x%2 == 1 && cel.y%2 == 0 ) { limit = GetCel(cel,0,-2); action = WM_ACTION_BATEAUAN; return true; } return false; } // Indique s'il est possible de sauter dans une direction. bool CDecor::IsFreeJump(POINT cel, int direct, int rank, int &action) { POINT depart, vector; int i, icon; int bits[3*3]; // Refuse de sauter si blupi n'est pas � pied ! if ( m_blupi[rank].vehicule != 0 ) return false; // Refuse de sauter dans les directions se, so, no, ne. if ( (direct/16)%2 != 0 ) return false; // Refuse de sauter si peu d'�nergie ou si porte qq chose. if ( m_blupi[rank].perso != 0 || m_blupi[rank].energy <= MAXENERGY/4 || m_blupi[rank].takeChannel != -1 ) return false; vector = GetVector(direct); depart = cel; i = 0; while ( true ) { cel.x += vector.x; cel.y += vector.y; if ( i == 4 ) break; if ( IsFreeCelFloor(cel, rank) ) break; i ++; } if ( i == 0 ) return false; // D�part possible par-rapport aux obstacles ? icon = m_decor[depart.x/2][depart.y/2].objectIcon; SearchObject(rank, icon, depart, bits); AjustObject(rank, icon, depart, bits); if ( bits[(1+vector.x)+(1+vector.y)*3] == 1 ) return false; // Arriv�e possible par-rapport aux obstacles ? icon = m_decor[cel.x/2][cel.y/2].objectIcon; SearchObject(rank, icon, cel, bits); AjustObject(rank, icon, cel, bits); if ( bits[(1-vector.x)+(1-vector.y)*3] == 1 ) return false; if ( !IsFreeCel(cel, rank) || IsBlupiHere(cel, true) ) return false; action = ACTION_SAUTE2+(i-1); return true; } // Indique s'il est possible de glisser dans une direction. bool CDecor::IsFreeGlisse(POINT cel, int direct, int rank, int &action) { int channel, icon; // Y'a que blupi qui glisse ! if ( m_blupi[rank].perso != 0 ) return false; GetFloor(GetCel((cel.x/2)*2,(cel.y/2)*2), channel, icon); if ( channel != CHFLOOR || icon != 18 ) // pas dalle glissante ? { return false; } if ( !IsFreeDirect(cel, direct, rank) ) return false; action = ACTION_GLISSE; return true; } // Cherche la meilleure direction pour atteindre un but. // Retourne -1 si on est d�j� sur le but. int CDecor::DirectSearch(POINT cel, POINT goal) { POINT dir; int direct, tan; dir.x = goal.x - cel.x; dir.y = goal.y - cel.y; if ( dir.x == 0 && dir.y == 0 ) // but atteint ? { return -1; } #if 0 if ( dir.x > 0 ) { if ( dir.y > 0 ) direct = DIRECT_SE; if ( dir.y == 0 ) direct = DIRECT_E; if ( dir.y < 0 ) direct = DIRECT_NE; } if ( dir.x == 0 ) { if ( dir.y > 0 ) direct = DIRECT_S; else direct = DIRECT_N; } if ( dir.x < 0 ) { if ( dir.y > 0 ) direct = DIRECT_SO; if ( dir.y == 0 ) direct = DIRECT_O; if ( dir.y < 0 ) direct = DIRECT_NO; } #endif // Cherche le huiti�me de cadrant correspondant � // la direction. // 41 = 100*tan(22.5) // 241 = 100*tan(67.5) if ( dir.x == 0 ) { if ( dir.y > 0 ) direct = DIRECT_S; else direct = DIRECT_N; } else { tan = abs(100*dir.y/dir.x); // calcule la tangente*100 if ( dir.x > 0 ) { if ( dir.y > 0 ) { direct = DIRECT_SE; if ( tan < 41 ) direct = DIRECT_E; if ( tan > 241 ) direct = DIRECT_S; } else { direct = DIRECT_NE; if ( tan < 41 ) direct = DIRECT_E; if ( tan > 241 ) direct = DIRECT_N; } } else { if ( dir.y > 0 ) { direct = DIRECT_SO; if ( tan < 41 ) direct = DIRECT_O; if ( tan > 241 ) direct = DIRECT_S; } else { direct = DIRECT_NO; if ( tan < 41 ) direct = DIRECT_O; if ( tan > 241 ) direct = DIRECT_N; } } } return direct; } // Vide les positions d�j� essay�es. void CDecor::FlushUsed(int rank) { m_blupi[rank].nbUsed = 0; m_blupi[rank].nextRankUsed = 0; } // Ajoute une position d�j� �t� essay�e. void CDecor::AddUsedPos(int rank, POINT pos) { int i, j, old; // Un virus est b�te. if ( m_blupi[rank].perso == 2 ) return; // D�j� dans la liste ? for ( i=0 ; i<m_blupi[rank].nbUsed ; i++ ) { if ( pos.x == m_blupi[rank].posUsed[i].x && pos.y == m_blupi[rank].posUsed[i].y ) { m_blupi[rank].rankUsed[i] = m_blupi[rank].nextRankUsed; m_blupi[rank].nextRankUsed ++; return; } } // Si la liste est pleine, remplace le plus vieux point. if ( m_blupi[rank].nbUsed >= MAXUSED ) { old = 10000; j = 0; for ( i=0 ; i<m_blupi[rank].nbUsed ; i++ ) { if ( m_blupi[rank].rankUsed[i] < old ) { old = m_blupi[rank].rankUsed[i]; j = i; } } m_blupi[rank].posUsed[j] = pos; m_blupi[rank].rankUsed[j] = m_blupi[rank].nextRankUsed; m_blupi[rank].nextRankUsed ++; return; } // Ajoute � la suite de la liste. i = m_blupi[rank].nbUsed; m_blupi[rank].posUsed[i] = pos; m_blupi[rank].rankUsed[i] = m_blupi[rank].nextRankUsed; m_blupi[rank].nbUsed ++; m_blupi[rank].nextRankUsed ++; return; } // Cherche si une position a d�j� �t� essay�e. bool CDecor::IsUsedPos(int rank, POINT pos) { int i; for ( i=0 ; i<m_blupi[rank].nbUsed ; i++ ) { if ( pos.x == m_blupi[rank].posUsed[i].x && pos.y == m_blupi[rank].posUsed[i].y ) return true; } return false; } // Cherche la meilleure direction pour atteindre un but. bool CDecor::SearchBestBase(int rank, int &action, POINT &newCel, int &direct) { int searchDirect[8] = {0,1,7,2,6,5,3,4}; int tryDirect, workBlupi, i, a; POINT cel, vector; bool bFree; cel = m_blupi[rank].cel; direct = DirectSearch(cel, m_blupi[rank].goalCel); AddUsedPos(rank, cel); for ( i=0 ; i<8 ; i++ ) { tryDirect = ((direct/16+searchDirect[i])%8)*16; vector = GetVector(tryDirect); bFree = IsFreeGlisse(cel, tryDirect, rank, action); if ( !bFree ) { bFree = IsFreeDirect(cel, tryDirect, rank); action = ACTION_MARCHE; } if ( !bFree ) { bFree = IsFreeJump(cel, tryDirect, rank, action); } a = GetAmplitude(action); // Blupi peut aller sur le lieu de la construction. if ( m_blupi[rank].passCel.x != -1 ) { newCel = m_blupi[rank].passCel; workBlupi = m_decor[newCel.x/2][newCel.y/2].workBlupi; if ( m_blupi[rank].passCel.x/2 == (cel.x+vector.x*a)/2 && m_blupi[rank].passCel.y/2 == (cel.y+vector.y*a)/2 && (workBlupi < 0 || workBlupi == rank) ) { bFree = true; } } if ( bFree ) { newCel.x = cel.x + vector.x*a; newCel.y = cel.y + vector.y*a; if ( !IsUsedPos(rank, newCel) ) { if ( m_blupi[rank].perso == 3 ) // tracks ? { // Le tracks peut aller sur les blupi // pour les �craser ! if ( IsTracksHere(newCel, false) ) { continue; } else { AddUsedPos(rank, newCel); direct = tryDirect; return true; } } else { if ( IsBlupiHere(newCel, false) ) { // Si blupi immobile, comme si obstacle qq. if ( m_blupi[m_blupiHere].goalCel.x == -1 ) continue; newCel = cel; action = ACTION_STOP; direct = tryDirect; return true; } else { AddUsedPos(rank, newCel); direct = tryDirect; return true; } } } } } return false; } // Cherche la meilleure direction pour atteindre un but. bool CDecor::SearchBestPass(int rank, int &action) { Blupi iBlupi; int i, j, direct; POINT iCel, lCel, cel; if ( m_blupi[rank].perso == 0 || // blupi ? m_blupi[rank].perso == 7 || // �lectro ? m_blupi[rank].perso == 8 || // disciple ? (m_blupi[rank].perso == 4 && // robot ? m_term.bHachRobot ) ) // robot sur dalles hachur�es ? { if ( m_blupi[rank].busyDelay > 0 ) { m_blupi[rank].busyDelay --; if ( m_blupi[rank].busyDelay == 0 && m_blupi[rank].busyCount > 0 ) { m_blupi[rank].busyCount --; } return false; } if ( CheminCherche(rank, action) ) // recherche fut�e selon DD ... { return true; } else { // Si la destination est occup�e pendant une r�p�tition, // il faut attendre � l'infini ! if ( m_blupi[rank].repeatLevel != -1 && IsBlupiHereEx(m_blupi[rank].goalCel, rank, false) ) { m_blupi[rank].busyCount ++; } m_blupi[rank].busyDelay = Random(8,12); // d�lai avant r�essai return false; } } for ( j=0 ; j<7 ; j++ ) { iBlupi = m_blupi[rank]; // sauvegarde blupi // Essaye 7 coups en avance, pour voir. iCel = m_blupi[rank].cel; i = 0; while ( true ) { if ( !SearchBestBase(rank, action, cel, direct) ) break; if ( action == ACTION_STOP ) // collision avec autre blupi ? { if ( i == 0 ) { m_blupi[rank] = iBlupi; // restitue blupi return false; } i = 7; // comme si ok pour 7 coups break; } m_blupi[rank].cel = cel; lCel = cel; // Est-on revenu juste � c�t� de la position // de d�part ? Si oui, simplifie le mouvement. if ( i > 1 && abs(m_blupi[rank].cel.x-iCel.x) <= 1 && abs(m_blupi[rank].cel.y-iCel.y) <= 1 ) { direct = DirectSearch(iCel, cel); if ( IsFreeDirect(iCel, direct, rank) ) { m_blupi[rank].cel = iCel; m_blupi[rank].sDirect = direct; action = ACTION_MARCHE; return true; } } // A-t-on atteint le but ? if ( cel.x == m_blupi[rank].goalCel.x && cel.y == m_blupi[rank].goalCel.y ) { i = 7; // comme si ok pour 7 coups break; } i ++; if ( i >= 7 ) break; } m_blupi[rank] = iBlupi; // restitue blupi if ( i == 0 ) return false; if ( i == 7 ) { SearchBestBase(rank, action, cel, direct); m_blupi[rank].sDirect = direct; return true; } AddUsedPos(rank, lCel); // bloque position ridicule } return false; } // V�rifie si un objet est utilisable pour travailler dessus. // Le sol doit permettre d'aller aux 4 coins, et il ne doit // pas y avoir un autre blupi que soi-m�me. bool CDecor::IsWorkableObject(POINT cel, int rank) { if ( !IsFreeCelFloor(GetCel(cel,0,0), -1) || !IsFreeCelFloor(GetCel(cel,1,0), -1) || !IsFreeCelFloor(GetCel(cel,0,1), -1) || !IsFreeCelFloor(GetCel(cel,1,1), -1) ) return false; if ( IsBlupiHereEx(GetCel(cel,0,0), rank, false) || IsBlupiHereEx(GetCel(cel,1,0), rank, false) || IsBlupiHereEx(GetCel(cel,0,1), rank, false) || IsBlupiHereEx(GetCel(cel,1,1), rank, false) ) return false; if ( m_decor[cel.x/2][cel.y/2].fire > 0 && m_decor[cel.x/2][cel.y/2].fire < MoveMaxFire() ) return false; return true; } // Cherche un autre objet pour continuer une action // (comme par exemple abatre des arbres). bool CDecor::SearchOtherObject(int rank, POINT initCel, int action, int distMax, int channel, int firstIcon1, int lastIcon1, int firstIcon2, int lastIcon2, POINT &foundCel, int &foundIcon) { int startx, starty, endx, endy; int x, y, xx, yy; int dist, min = distMax; POINT cel; bool bOK; if ( firstIcon1 == 33 && lastIcon1 == 48 && firstIcon2 == 71 && lastIcon2 == 71 ) // cherche du fer ? { return SearchOtherDrapeau(rank, initCel, distMax, foundCel, foundIcon); } initCel.x = (initCel.x/2)*2; initCel.y = (initCel.y/2)*2; startx = ((initCel.x-distMax/2)/2)*2; endx = ((initCel.x+distMax/2)/2)*2; starty = ((initCel.y-distMax/2)/2)*2; endy = ((initCel.y+distMax/2)/2)*2; if ( startx < 0 ) startx = 0; if ( endx > MAXCELX ) endx = MAXCELX; if ( starty < 0 ) starty = 0; if ( endy > MAXCELY ) endy = MAXCELY; if ( firstIcon2 == -1 && lastIcon2 == -1 ) { firstIcon2 = 22222; lastIcon2 = 22222; } for ( y=starty ; y<endy ; y+=2 ) { for ( x=startx ; x<endx ; x+=2 ) { bOK = false; if ( channel == CHFLOOR ) { if ( m_decor[x/2][y/2].floorChannel == channel && ((m_decor[x/2][y/2].floorIcon >= firstIcon1 && m_decor[x/2][y/2].floorIcon <= lastIcon1 )|| (m_decor[x/2][y/2].floorIcon >= firstIcon2 && m_decor[x/2][y/2].floorIcon <= lastIcon2 ))&& m_decor[x/2][y/2].objectChannel == -1 ) bOK = true; } else { if ( m_decor[x/2][y/2].objectChannel == channel && ((m_decor[x/2][y/2].objectIcon >= firstIcon1 && m_decor[x/2][y/2].objectIcon <= lastIcon1 )|| (m_decor[x/2][y/2].objectIcon >= firstIcon2 && m_decor[x/2][y/2].objectIcon <= lastIcon2 )) ) bOK = true; } if ( bOK ) { cel.x = x; cel.y = y; if ( BlupiIsGoalUsed(cel) ) continue; if ( action == WM_ACTION_ABAT1 || action == WM_ACTION_BUILD1 || action == WM_ACTION_BUILD2 || action == WM_ACTION_BUILD3 || action == WM_ACTION_BUILD4 || action == WM_ACTION_BUILD5 || action == WM_ACTION_BUILD6 || action == WM_ACTION_ROC1 || action == WM_ACTION_MUR || action == WM_ACTION_PONTE || action == WM_ACTION_TOUR || action == WM_ACTION_BATEAUE || action == WM_ACTION_CULTIVE2 || action == WM_ACTION_DRAPEAU2 || action == WM_ACTION_DEPOSE ) { if ( !IsWorkableObject(cel, rank) ) continue; } dist = abs(initCel.x-x) + abs(initCel.y-y); if ( dist <= min ) { min = dist; xx = x; yy = y; } } } } if ( min == distMax ) return false; foundCel.x = xx; foundCel.y = yy; if ( channel == CHFLOOR ) { foundIcon = m_decor[xx/2][yy/2].floorIcon; } else { foundIcon = m_decor[xx/2][yy/2].objectIcon; } return true; } // Cherche un autre sol pouvant contenir du fer, pour y // planter un drapeau. bool CDecor::SearchOtherDrapeau(int rank, POINT initCel, int distMax, POINT &foundCel, int &foundIcon) { int startx, starty, endx, endy, icon; int x, y; int dist, min = distMax; POINT cel; startx = ((initCel.x-distMax/2)/2)*2; endx = ((initCel.x+distMax/2)/2)*2; starty = ((initCel.y-distMax/2)/2)*2; endy = ((initCel.y+distMax/2)/2)*2; if ( startx < 0 ) startx = 0; if ( endx > MAXCELX ) endx = MAXCELX; if ( starty < 0 ) starty = 0; if ( endy > MAXCELY ) endy = MAXCELY; for ( y=starty ; y<endy ; y+=2 ) { for ( x=startx ; x<endx ; x+=2 ) { icon = m_decor[x/2][y/2].floorIcon; if ( m_decor[x/2][y/2].objectIcon == -1 && ((icon >= 33 && icon <= 48) || // terre ? icon == 71 ) && !TestDrapeau(GetCel(x,y)) ) // pas encore sond� ? { cel.x = x; cel.y = y; if ( BlupiIsGoalUsed(cel) ) continue; if ( !IsWorkableObject(cel, rank) ) continue; dist = abs(initCel.x-x) + abs(initCel.y-y); if ( dist <= min ) { min = dist; foundCel.x = x; foundCel.y = y; foundIcon = icon; } } } } if ( min == distMax ) return false; return true; } // Cherche un autre sol permettant de d�poser du bois // pour construire un bateau. bool CDecor::SearchOtherBateau(int rank, POINT initCel, int distMax, POINT &foundCel, int &foundIcon) { int startx, starty, endx, endy; int x, y, direct; int dist, min = distMax; startx = ((initCel.x-distMax/2)/2)*2; endx = ((initCel.x+distMax/2)/2)*2; starty = ((initCel.y-distMax/2)/2)*2; endy = ((initCel.y+distMax/2)/2)*2; if ( startx < 0 ) startx = 0; if ( endx > MAXCELX ) endx = MAXCELX; if ( starty < 0 ) starty = 0; if ( endy > MAXCELY ) endy = MAXCELY; for ( y=starty ; y<endy ; y+=2 ) { for ( x=startx ; x<endx ; x+=2 ) { if ( !IsBuildBateau(GetCel(x,y), direct) ) continue; dist = abs(initCel.x-x) + abs(initCel.y-y); if ( dist <= min ) { min = dist; foundCel.x = x; foundCel.y = y; foundIcon = m_decor[x/2][y/2].floorIcon; } } } if ( min == distMax ) return false; return true; } // V�rifie si l'objet peut �tre d�truit par l'araign�e. bool CDecor::IsSpiderObject(int icon) { return ( icon == 60 || // tomates ? icon == 92 || // poison ? icon == 93 ); // pi�ge ? } // Cherche un autre objet pour l'araign�e. bool CDecor::SearchSpiderObject(int rank, POINT initCel, int distMax, POINT &foundCel, int &foundIcon) { int startx, starty, endx, endy; int x, y; int dist, min = distMax; POINT cel; startx = ((initCel.x-distMax/2)/2)*2; endx = ((initCel.x+distMax/2)/2)*2; starty = ((initCel.y-distMax/2)/2)*2; endy = ((initCel.y+distMax/2)/2)*2; if ( startx < 0 ) startx = 0; if ( endx > MAXCELX ) endx = MAXCELX; if ( starty < 0 ) starty = 0; if ( endy > MAXCELY ) endy = MAXCELY; for ( y=starty ; y<endy ; y+=2 ) { for ( x=startx ; x<endx ; x+=2 ) { if ( IsSpiderObject(m_decor[x/2][y/2].objectIcon) ) { cel.x = x; cel.y = y; if ( IsBlupiHere(cel, false) ) continue; dist = abs(initCel.x-x) + abs(initCel.y-y); if ( m_decor[x/2][y/2].objectIcon == 93 && //pi�ge ? dist > 4 ) continue; // si pi�ge loin -> ignore if ( dist <= min ) { min = dist; foundCel.x = x+1; foundCel.y = y+1; // +1 -> sur l'objet foundIcon = m_decor[x/2][y/2].objectIcon; } } } } if ( min == distMax ) return false; return true; } // V�rifie si l'objet peut �tre d�truit par le tracks. bool CDecor::IsTracksObject(int icon) { return ( icon == 36 || // planches ? icon == 44 || // pierres ? icon == 60 || // tomates ? icon == 63 || // oeufs ? icon == 80 || // bouteille ? icon == 85 || // dynamite ? icon == 92 || // poison ? icon == 93 || // pi�ge ? icon == 123 || // pi�ge ? icon == 125 || // mine ? icon == 127 || // mine ? (icon >= 81 && icon <= 84) || // fleurs ? (icon >= 94 && icon <= 95) ); // fleurs ? } // Cherche un autre objet pour le tracks. bool CDecor::SearchTracksObject(int rank, POINT initCel, int distMax, POINT &foundCel, int &foundIcon) { int startx, starty, endx, endy, icon; int x, y; int dist, min = distMax; //? POINT cel; startx = ((initCel.x-distMax/2)/2)*2; endx = ((initCel.x+distMax/2)/2)*2; starty = ((initCel.y-distMax/2)/2)*2; endy = ((initCel.y+distMax/2)/2)*2; if ( startx < 0 ) startx = 0; if ( endx > MAXCELX ) endx = MAXCELX; if ( starty < 0 ) starty = 0; if ( endy > MAXCELY ) endy = MAXCELY; for ( y=starty ; y<endy ; y+=2 ) { for ( x=startx ; x<endx ; x+=2 ) { if ( IsTracksObject(m_decor[x/2][y/2].objectIcon) ) { //? cel.x = x; //? cel.y = y; //? if ( BlupiIsGoalUsed(cel) ) continue; //? if ( IsBlupiHere(cel, false) ) continue; dist = abs(initCel.x-x) + abs(initCel.y-y); if ( dist <= min ) { min = dist; foundCel.x = x+1; foundCel.y = y+1; // +1 -> sur l'objet foundIcon = m_decor[x/2][y/2].objectIcon; } } } } // Le tracks peut �craser blupi. for ( rank=0 ; rank<MAXBLUPI ; rank++ ) { if ( m_blupi[rank].bExist && m_blupi[rank].perso == 0 && // blupi ? m_blupi[rank].vehicule == 0 ) // � pied ? { //? if ( BlupiIsGoalUsed(m_blupi[rank].cel) ) continue; x = m_blupi[rank].cel.x; y = m_blupi[rank].cel.y; icon = m_decor[x/2][y/2].objectIcon; if ( icon == 113 || // maison ? icon == 28 || icon == 29 || // laboratoire ? icon == 119 || icon == 120 || // usine ? icon == 121 || icon == 122 ) // mine de fer ? { continue; } dist = abs(initCel.x-x) + abs(initCel.y-y); if ( dist <= min ) { min = dist; foundCel.x = x; foundCel.y = y; foundIcon = -1; // blupi (pas un objet) ! } } } if ( min == distMax ) return false; return true; } // V�rifie si l'objet peut �tre d�truit par le robot. bool CDecor::IsRobotObject(int icon) { return ( icon == 85 || // dynamite ? icon == 93 || // pi�ge ? icon == 125 || // mine ? icon == 127 ); // mine ? } // Cherche une autre action pour le robot. // C'est ici qu'est contenue l'IA du robot ! bool CDecor::SearchRobotObject(int rank, POINT initCel, int distMax, POINT &foundCel, int &foundIcon, int &foundAction) { int startx, starty, endx, endy; int x, y; int dist, maxUsine, min = distMax; int nbUsine[10]; int nbPerso[10]; int i, r, d, dd, icon, index, nb; if ( m_term.bHachRobot ) // robot sur dalles hachur�es ? { foundAction = WM_ACTION_GO; return SearchOtherObject(rank, initCel, WM_ACTION_GO, 200, CHFLOOR,17,17,-1,-1, foundCel, foundIcon); } initCel.x = (initCel.x/2)*2; initCel.y = (initCel.y/2)*2; // b�timents tr�s espac�s ! startx = ((initCel.x-distMax/2)/2)*2; endx = ((initCel.x+distMax/2)/2)*2; starty = ((initCel.y-distMax/2)/2)*2; endy = ((initCel.y+distMax/2)/2)*2; for ( i=0 ; i<10 ; i++ ) { nbUsine[i] = 0; } if ( startx < 0 ) startx = 0; if ( endx > MAXCELX ) endx = MAXCELX; if ( starty < 0 ) starty = 0; if ( endy > MAXCELY ) endy = MAXCELY; for ( y=starty ; y<endy ; y+=2 ) { for ( x=startx ; x<endx ; x+=2 ) { icon = m_decor[x/2][y/2].objectIcon; if ( icon == 99 ) nbUsine[0] ++; // recharge ? if ( icon == 104 ) nbUsine[1] ++; // usine tracks ? if ( icon == 100 ) nbUsine[2] ++; // usine araign�e ? if ( icon == 102 ) nbUsine[3] ++; // usine virus ? if ( icon == 115 ) nbUsine[4] ++; // usine bombe ? if ( icon == 17 ) nbUsine[5] ++; // usine �lectro ? dist = abs(initCel.x-x) + abs(initCel.y-y); if ( IsRobotObject(icon) && // pi�ge/dynamite ? dist <= 4 ) // tr�s proche ? { if ( dist <= min ) { min = dist; foundCel.x = x+1; foundCel.y = y+1; // +1 -> sur l'objet foundIcon = m_decor[x/2][y/2].objectIcon; } } } } if ( min < distMax ) { foundAction = -1; // robot passe tout pr�t d'un pi�ge/dynamite return true; } // Cherche l'usine la moins construite. min = 999; maxUsine = 0; index = 0; for ( i=0 ; i<6 ; i++ ) { if ( nbUsine[i] < min ) { min = nbUsine[i]; index = i; } if ( nbUsine[i] > maxUsine ) { maxUsine = nbUsine[i]; } } //? if ( nbUsine[0] > 0 && // sation de recharge existe ? //? m_blupi[rank].energy <= MAXENERGY/2 ) // peu de forces ? //? { //? index = 0; // station de recharge //? goto search; //? } if ( min == 0 ) // encore une usine � construire ? { // Libre juste ici ? if ( IsUsineBuild(rank, initCel) ) { foundCel = initCel; build: if ( index == 0 ) foundAction = WM_ACTION_R_BUILD1; // recharge if ( index == 1 ) foundAction = WM_ACTION_R_BUILD4; // tracks if ( index == 2 ) foundAction = WM_ACTION_R_BUILD2; // araign�e if ( index == 3 ) foundAction = WM_ACTION_R_BUILD3; // virus if ( index == 4 ) foundAction = WM_ACTION_R_BUILD5; // bombe if ( index == 5 ) foundAction = WM_ACTION_R_BUILD6; // �lectro return true; } // Cherche un emplacement libre. for ( d=1 ; d<distMax/6 ; d++ ) { x = initCel.x + d*6; y = initCel.y - d*6; for ( i=0 ; i<4 ; i++ ) // 4 directions { for ( dd=0 ; dd<=d ; dd++ ) { if ( i == 0 ) x -= 6; // � gauche if ( i == 1 ) y += 6; // descend if ( i == 2 ) x += 6; // � droite if ( i == 3 ) y -= 6; // monte if ( IsUsineBuild(rank, GetCel(x,y)) ) { foundCel.x = x; foundCel.y = y; goto build; } } } } } // Cherche l'ennemi le moins r�pandu. for ( i=0 ; i<10 ; i++ ) { nbPerso[i] = 0; } nb = 0; for ( r=0 ; r<MAXBLUPI ; r++ ) { if ( m_blupi[r].bExist ) { nb ++; if ( m_blupi[r].perso == 3 ) // tracks ? { nbPerso[0] += 1; } if ( m_blupi[r].perso == 1 ) // araign�e ? { nbPerso[1] += 1; } if ( m_blupi[r].perso == 2 ) // virus ? { nbPerso[2] += 1; } if ( m_blupi[r].perso == 5 ) // bombe ? { nbPerso[3] += 2; } if ( m_blupi[r].perso == 7 ) // �lectro ? { nbPerso[4] += 2; } } } if ( nb > MAXBLUPI-10 ) return false; // rien si trop peupl� ! // Cherche l'ennemi le moins r�pandu. min = 999; index = 0; for ( i=0 ; i<5 ; i++ ) { if ( nbPerso[i] < min && nbUsine[i+1] != 0 ) // usine correspondante existe ? { min = nbPerso[i]; index = i+1; } } if ( m_blupi[rank].energy <= MAXENERGY/2 ) // peu de forces ? { index = 0; // station de recharge } if ( m_skill >= 1 ) maxUsine *= 2; // 2 ennemis par batiment if ( min >= maxUsine ) // assez peupl� ? { index = 0; // station de recharge } // Cherche l'usine pour fabriquer l'ennemi le moins r�dandu. //? search: min = distMax; for ( y=starty ; y<endy ; y+=2 ) { for ( x=startx ; x<endx ; x+=2 ) { icon = m_decor[x/2][y/2].objectIcon; if ( (index == 0 && icon == 99) || // recharge ? (index == 1 && icon == 104) || // tracks ? (index == 2 && icon == 100) || // araign�e ? (index == 3 && icon == 102) || // virus ? (index == 4 && icon == 115) || // bombe ? (index == 5 && icon == 17) ) // �lectro ? { if ( IsUsineFree(rank, GetCel(x,y)) ) { dist = abs(initCel.x-x) + abs(initCel.y-y); if ( dist <= min ) { min = dist; foundCel.x = x; foundCel.y = y; // dans l'usine foundIcon = icon; } } } } } if ( min < distMax ) { if ( index == 0 ) foundAction = WM_ACTION_R_MAKE1; // recharge if ( index == 1 ) foundAction = WM_ACTION_R_MAKE4; // tracks if ( index == 2 ) foundAction = WM_ACTION_R_MAKE2; // araign�e if ( index == 3 ) foundAction = WM_ACTION_R_MAKE3; // virus if ( index == 4 ) foundAction = WM_ACTION_R_MAKE5; // bombe if ( index == 5 ) foundAction = WM_ACTION_R_MAKE6; // �lectro return true; } // Cherche l'usine la plus proche. min = distMax; for ( y=starty ; y<endy ; y+=2 ) { for ( x=startx ; x<endx ; x+=2 ) { icon = m_decor[x/2][y/2].objectIcon; if ( (icon == 100 && nbPerso[1] <= maxUsine) || // araign�e ? (icon == 102 && nbPerso[2] <= maxUsine) || // virus ? (icon == 104 && nbPerso[0] <= maxUsine) || // tracks ? (icon == 115 && nbPerso[3] <= maxUsine) || // bombe ? (icon == 17 && nbPerso[4] <= maxUsine) ) // �lectro ? { if ( IsUsineFree(rank, GetCel(x,y)) ) { dist = abs(initCel.x-x) + abs(initCel.y-y); if ( dist <= min ) { min = dist; foundCel.x = x; foundCel.y = y; // dans l'usine foundIcon = icon; } } } } } if ( min < distMax ) { if ( foundIcon == 100 ) foundAction = WM_ACTION_R_MAKE2; // araign�e if ( foundIcon == 102 ) foundAction = WM_ACTION_R_MAKE3; // virus if ( foundIcon == 104 ) foundAction = WM_ACTION_R_MAKE4; // tracks if ( foundIcon == 115 ) foundAction = WM_ACTION_R_MAKE5; // bombe if ( foundIcon == 17 ) foundAction = WM_ACTION_R_MAKE6; // �lectro return true; } return false; } // Teste si un emplacement est ok pour b�tir une usine. bool CDecor::IsUsineBuild(int rank, POINT cel) { int icon, channel; int x, y; // Pas sur les dalles hachur�es ! GetFloor(cel, channel, icon); if ( channel == CHFLOOR && (icon < 65 || icon > 67) ) return false; for ( x=-1 ; x<3 ; x++ ) { for ( y=-1 ; y<3 ; y++ ) { if ( !IsFreeCel(GetCel(cel,x,y), rank) || IsBlupiHereEx(GetCel(cel,x,y), rank, false) ) { return false; } } } return true; } // Teste s'il est possible d'entrer dans une usine. // L'usine doit �tre libre devant (lieu de stationnement // pour l'ennemi qui sera construit). bool CDecor::IsUsineFree(int rank, POINT cel) { int channel, icon; GetObject(cel, channel, icon); if ( channel == CHOBJECT && icon == 115 ) // usine � bombes ? { return ( !IsBlupiHereEx(GetCel(cel,0,1), rank, false) && !IsBlupiHereEx(GetCel(cel,1,1), rank, false) && !IsBlupiHereEx(GetCel(cel,2,1), rank, false) && !IsBlupiHereEx(GetCel(cel,3,1), rank, false) ); } return ( !IsBlupiHereEx(GetCel(cel,0,1), rank, false) && !IsBlupiHereEx(GetCel(cel,1,1), rank, false) && !IsBlupiHereEx(GetCel(cel,2,0), rank, false) && !IsBlupiHereEx(GetCel(cel,2,1), rank, false) && (!IsBlupiHereEx(GetCel(cel,3,0), rank, false)|| !IsBlupiHereEx(GetCel(cel,3,1), rank, false)) ); } // V�rifie si l'objet peut �tre d�truit par une bombe. bool CDecor::IsBombeObject(int icon) { return ( icon == 36 || // planches ? icon == 61 || // cabane ? icon == 121 || icon == 122 || // mine de fer ? (icon >= 65 && icon <= 71) || // palissade ? icon == 93 || // pi�ge ? icon == 117 ); // bateau ? } // Cherche un autre objet pour une bombe. bool CDecor::SearchBombeObject(int rank, POINT initCel, int distMax, POINT &foundCel, int &foundIcon) { int startx, starty, endx, endy; int x, y; int dist, min = distMax; POINT cel; startx = ((initCel.x-distMax/2)/2)*2; endx = ((initCel.x+distMax/2)/2)*2; starty = ((initCel.y-distMax/2)/2)*2; endy = ((initCel.y+distMax/2)/2)*2; if ( startx < 0 ) startx = 0; if ( endx > MAXCELX ) endx = MAXCELX; if ( starty < 0 ) starty = 0; if ( endy > MAXCELY ) endy = MAXCELY; for ( y=starty ; y<endy ; y+=2 ) { for ( x=startx ; x<endx ; x+=2 ) { if ( IsBombeObject(m_decor[x/2][y/2].objectIcon) ) { cel.x = x; cel.y = y; if ( IsBlupiHere(cel, false) ) continue; dist = abs(initCel.x-x) + abs(initCel.y-y); if ( m_decor[x/2][y/2].objectIcon == 93 && //pi�ge ? dist > 8 ) continue; // si pi�ge loin -> ignore if ( dist <= min ) { min = dist; foundCel.x = x+1; foundCel.y = y+1; // +1 -> sur l'objet foundIcon = m_decor[x/2][y/2].objectIcon; } } } } if ( min == distMax ) return false; return true; } // Cherche un autre objet pour un �lectro. bool CDecor::SearchElectroObject(int rank, POINT initCel, int distMax, POINT &foundCel, int &foundIcon) { int startx, starty, endx, endy; int x, y, i, d, dd, r; int dist, min = distMax; POINT cel; startx = ((initCel.x-10/2)/2)*2; endx = ((initCel.x+10/2)/2)*2; starty = ((initCel.y-10/2)/2)*2; endy = ((initCel.y+10/2)/2)*2; if ( startx < 0 ) startx = 0; if ( endx > MAXCELX ) endx = MAXCELX; if ( starty < 0 ) starty = 0; if ( endy > MAXCELY ) endy = MAXCELY; for ( y=starty ; y<endy ; y+=2 ) { for ( x=startx ; x<endx ; x+=2 ) { if ( m_decor[x/2][y/2].objectIcon == 93 ) // pi�ge ? { cel.x = x; cel.y = y; if ( IsBlupiHere(cel, false) ) continue; dist = abs(initCel.x-x) + abs(initCel.y-y); if ( dist <= 4 ) { min = dist; foundCel.x = x+1; foundCel.y = y+1; // +1 -> sur l'objet foundIcon = m_decor[x/2][y/2].objectIcon; } } } } if ( min <= 4 ) return true; min = distMax; for ( r=0 ; r<MAXBLUPI ; r++ ) { if ( m_blupi[r].bExist && m_blupi[r].perso == 0 && // blupi ? m_blupi[r].goalAction != WM_ACTION_ELECTRO ) { //? if ( BlupiIsGoalUsed(m_blupi[r].cel) ) continue; x = m_blupi[r].cel.x; y = m_blupi[r].cel.y; dist = abs(initCel.x-x) + abs(initCel.y-y); if ( dist <= distMax/2 && dist <= min ) { min = dist; foundCel.x = x; foundCel.y = y; foundIcon = -1; // blupi (pas un objet) ! } } } if ( min == distMax ) return false; // Cherche un emplacement libre. for ( d=1 ; d<distMax/2 ; d++ ) { x = foundCel.x + d; y = foundCel.y - d; for ( i=0 ; i<4 ; i++ ) // 4 directions { for ( dd=0 ; dd<=d ; dd++ ) { if ( i == 0 ) x -= 1; // � gauche if ( i == 1 ) y += 1; // descend if ( i == 2 ) x += 1; // � droite if ( i == 3 ) y -= 1; // monte if ( IsFreeCel(GetCel(x,y), rank) && !IsBlupiHereEx(GetCel(x,y), rank, false) ) { foundCel.x = x; foundCel.y = y; return true; } } } } return false; } // Teste si une position est tr�s proche du feu. // Si oui, retourne true. bool CDecor::IsFireCel(POINT cel) { int x, y; POINT test; cel.x = (cel.x/2)*2; cel.y = (cel.y/2)*2; for ( x=-2 ; x<3 ; x+=2 ) { for ( y=-2 ; y<3 ; y+=2 ) { test.x = cel.x + x; test.y = cel.y + y; if ( !IsValid(test) ) continue; if ( m_decor[test.x/2][test.y/2].fire > 0 && m_decor[test.x/2][test.y/2].fire < MoveMaxFire() ) return true; } } return false; } // Teste si une position est tr�s proche d'un virus. // Si oui, retourne true. bool CDecor::IsVirusCel(POINT cel) { int rank; for ( rank=0 ; rank<MAXBLUPI ; rank++ ) { if ( m_blupi[rank].bExist && m_blupi[rank].perso == 2 ) // virus ? { if ( cel.x >= m_blupi[rank].cel.x-1 && cel.x <= m_blupi[rank].cel.x+1 && cel.y >= m_blupi[rank].cel.y-1 && cel.y <= m_blupi[rank].cel.y+1 ) return true; } } return false; } // Regarde s'il est possible de construire un pont � partir // d'une cellule donn�e (cel). // Retourne 0 si c'est possible, ou une erreur autrement ! int CDecor::IsBuildPont(POINT &cel, int &iconBuild) { POINT vector, test; int i, channel, icon, p1, p2, p3, r1, r2, nb, rest; int error = ERROR_MISC; for ( i=0 ; i<4 ; i++ ) { vector.x = 0; vector.y = 0; GetFloor(GetCel(cel,+2,0), channel, icon); if ( i == 0 && channel == CHFLOOR && (icon == 2 || icon == 59) ) // rivage ? { vector.x = +1; vector.y = 0; p1 = 59; p2 = 60; p3 = 61; r1 = 2; r2 = 4; } GetFloor(GetCel(cel,-2,0), channel, icon); if ( i == 1 && channel == CHFLOOR && (icon == 4 || icon == 61) ) // rivage ? { vector.x = -1; vector.y = 0; p1 = 61; p2 = 60; p3 = 59; r1 = 4; r2 = 2; } GetFloor(GetCel(cel,0,+2), channel, icon); if ( i == 2 && channel == CHFLOOR && (icon == 3 || icon == 62) ) // rivage ? { vector.x = 0; vector.y = +1; p1 = 62; p2 = 63; p3 = 64; r1 = 3; r2 = 5; } GetFloor(GetCel(cel,0,-2), channel, icon); if ( i == 3 && channel == CHFLOOR && (icon == 5 || icon == 64) ) // rivage ? { vector.x = 0; vector.y = -1; p1 = 64; p2 = 63; p3 = 62; r1 = 5; r2 = 3; } if ( vector.x == 0 && vector.y == 0 ) continue; // Avance tant que le pont existe. test = cel; nb = 0; do { test.x += vector.x*2; test.y += vector.y*2; if ( test.x < 0 || test.x >= MAXCELX || test.y < 0 || test.y >= MAXCELY ) break; if ( !GetFloor(test, channel, icon) ) continue; nb ++; } while ( icon == p1 || icon == p2 ); test.x -= vector.x*2; test.y -= vector.y*2; if ( icon == p3 ) { error = ERROR_PONTTERM; continue; } if ( nb == 1 ) iconBuild = p1; else iconBuild = p2; // Avance jusqu'� la rive oppos�e. rest = 0; do { test.x += vector.x*2; test.y += vector.y*2; if ( test.x < 0 || test.x >= MAXCELX || test.y < 0 || test.y >= MAXCELY ) break; if ( !GetFloor(test, channel, icon) ) continue; rest ++; } while ( icon == r1 || icon == 14 ); if ( icon == r2 && rest == 1 ) iconBuild = p3; if ( icon != r2 && icon != p2 && icon != p3 ) { error = ERROR_PONTOP; continue; } cel.x += vector.x*2*nb; cel.y += vector.y*2*nb; return 0; // ok } return error; } // Regarde s'il est possible de construire un bateau � partir // d'une cellule donn�e (cel). bool CDecor::IsBuildBateau(POINT cel, int &direct) { int fChannel, fIcon; int oChannel, oIcon; GetFloor (GetCel(cel,+2,0), fChannel, fIcon); GetObject(GetCel(cel,+2,0), oChannel, oIcon); if ( fChannel == CHFLOOR && fIcon == 2 && // rivage ? oChannel == -1 && oIcon == -1 ) { direct = DIRECT_E; return true; } GetFloor (GetCel(cel,-2,0), fChannel, fIcon); GetObject(GetCel(cel,-2,0), oChannel, oIcon); if ( fChannel == CHFLOOR && fIcon == 4 && // rivage ? oChannel == -1 && oIcon == -1 ) { direct = DIRECT_O; return true; } GetFloor (GetCel(cel,0,+2), fChannel, fIcon); GetObject(GetCel(cel,0,+2), oChannel, oIcon); if ( fChannel == CHFLOOR && fIcon == 3 && // rivage ? oChannel == -1 && oIcon == -1 ) { direct = DIRECT_S; return true; } GetFloor (GetCel(cel,0,-2), fChannel, fIcon); GetObject(GetCel(cel,0,-2), oChannel, oIcon); if ( fChannel == CHFLOOR && fIcon == 5 && // rivage ? oChannel == -1 && oIcon == -1 ) { direct = DIRECT_N; return true; } direct = -1; return false; } // Vide toutes les positions visit�es. void CDecor::InitDrapeau() { int i; for ( i=0 ; i<MAXLASTDRAPEAU ; i++ ) { m_lastDrapeau[i].x = -1; m_lastDrapeau[i].y = -1; } } // M�morise une cellule visit�e (ne contenant pas de fer). void CDecor::AddDrapeau(POINT cel) { int i; if ( TestDrapeau(cel) ) return; // d�j� dans la liste for ( i=MAXLASTDRAPEAU-1 ; i>0 ; i-- ) { m_lastDrapeau[i] = m_lastDrapeau[i-1]; } m_lastDrapeau[0] = cel; } // Supprime une cellule visit�e (ne contenant pas de fer). void CDecor::SubDrapeau(POINT cel) { int i; for ( i=0 ; i<MAXLASTDRAPEAU ; i++ ) { if ( cel.x == m_lastDrapeau[i].x && cel.y == m_lastDrapeau[i].y ) { m_lastDrapeau[i].x = -1; m_lastDrapeau[i].y = -1; } } } // Teste si une cellule a d�j� �t� visit�e. bool CDecor::TestDrapeau(POINT cel) { int i; for ( i=0 ; i<MAXLASTDRAPEAU ; i++ ) { if ( cel.x == m_lastDrapeau[i].x && cel.y == m_lastDrapeau[i].y ) return true; } return false; }