game.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  1. /*
  2. * File: game.c
  3. * Author: Arthur Brandao
  4. *
  5. * Created on 28 novembre 2018
  6. */
  7. #define _XOPEN_SOURCE 500
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include "error.h"
  11. #include "str.h"
  12. #include "file.h"
  13. #include "game.h"
  14. #include "bomberstudent_server.h"
  15. /* --- Extern --- */
  16. Game game[MAXGAME];
  17. int nbGame = 0;
  18. pthread_mutex_t gameMutex[MAXGAME];
  19. pthread_mutex_t playerMutex[MAXGAME * MAXPLAYER];
  20. /* --- Fonctions privées --- */
  21. /**
  22. * Transforme le fichier map en un tableau 2D
  23. * @param char* Le contenu du fichier map
  24. * @param int Largeur de la map
  25. * @param int Hauteur de la map
  26. * @return char** La map parser
  27. */
  28. char** parse_map(char* mapContent, int width, int height) {
  29. char** map = malloc(sizeof (char*) * width);
  30. //Creation des colonnes
  31. for (int i = 0; i < width; i++) {
  32. map[i] = malloc(sizeof (char) * height);
  33. }
  34. //Remplissage
  35. for (int i = 0; i < height; i++) {
  36. for (int j = 0; j < width; j++) {
  37. map[j][i] = *mapContent;
  38. mapContent++;
  39. }
  40. mapContent++;
  41. }
  42. return map;
  43. }
  44. /**
  45. * Transforme un tableau 2D en une chaine
  46. * @param char** Le contenu du fichier map
  47. * @param int Largeur de la map
  48. * @param int Hauteur de la map
  49. * @return char* La map
  50. */
  51. char* unparse_map(char** map, int width, int height) {
  52. int pos = 0;
  53. char* mapContent = malloc(sizeof (char) * (width * height + 1));
  54. memset(mapContent, 0, width * height + 1);
  55. //Remplissage
  56. for (int i = 0; i < height; i++) {
  57. for (int j = 0; j < width; j++) {
  58. mapContent[pos++] = map[j][i];
  59. }
  60. }
  61. return mapContent;
  62. }
  63. /**
  64. * Cherche le joueur à qui appartient un objet
  65. * @param Game* La game du joueur
  66. * @param int Le type de l'objet
  67. * @param int X de l'objet
  68. * @param int Y de l'objet
  69. * @return Player* Le joueur trouvé ou NULL
  70. */
  71. Player* search_player_object(Game* g, int type, int x, int y) {
  72. obj_node* objn;
  73. for (int i = 0; i < MAXPLAYER; i++) {
  74. if (g->player[i]->ini) {
  75. objn = object_search(g->player[i]->bomb, type, x, y);
  76. if (objn != NULL) {
  77. return g->player[i];
  78. }
  79. }
  80. }
  81. return NULL;
  82. }
  83. /* --- Fonctions publiques --- */
  84. boolean ini_games() {
  85. //Ini les games
  86. for (int i = 0; i < MAXGAME; i++) {
  87. game[i].active = false;
  88. game[i].index = i;
  89. }
  90. //Ini les mutex des games
  91. for (int i = 0; i < MAXGAME; i++) {
  92. if (pthread_mutex_init(&gameMutex[i], NULL) != 0) {
  93. adderror("Impossible d'initialiser les mutex des games");
  94. return false;
  95. }
  96. }
  97. //Ini les mutex des joueurs des games
  98. for (int i = 0; i < MAXGAME * MAXPLAYER; i++) {
  99. if (pthread_mutex_init(&playerMutex[i], NULL) != 0) {
  100. adderror("Impossible d'initialiser les mutex des joueurs");
  101. return false;
  102. }
  103. }
  104. return true;
  105. }
  106. void list_map(JsonArray* res) {
  107. char** result;
  108. int nbResult;
  109. //Regarde les fichiers dans le dossier
  110. result = file_list(MAPDIR, &nbResult);
  111. for (int i = 0; i < nbResult; i++) {
  112. add_array_string(res, result[i]);
  113. free(result[i]);
  114. }
  115. free(result);
  116. }
  117. int list_game(JsonArray* res) {
  118. JsonEncoder gameJson;
  119. int compteur = 0, i = 0;
  120. //Si il n' y a aucune game
  121. if (nbGame == 0) {
  122. return 0;
  123. }
  124. //Initialisation json
  125. ini_encoder(&gameJson);
  126. //Ajoute chaque game
  127. while (compteur < nbGame && i < MAXGAME) {
  128. pthread_mutex_lock(&gameMutex[i]);
  129. if (!game[i].active) {
  130. pthread_mutex_unlock(&gameMutex[i]);
  131. i++;
  132. continue;
  133. }
  134. //Creation objet json
  135. add_string(&gameJson, "name", game[i].name);
  136. add_integer(&gameJson, "nbPlayer", game[i].nbPlayer);
  137. add_string(&gameJson, "map", game[i].mapName);
  138. //Ajout dans le tableau
  139. add_array_object(res, &gameJson);
  140. //Nettoyage encoder objet
  141. clean_json_encoder(&gameJson);
  142. //Incremente
  143. pthread_mutex_unlock(&gameMutex[i]);
  144. i++;
  145. compteur++;
  146. }
  147. return nbGame;
  148. }
  149. int* map_size(char* map) {
  150. int* res;
  151. res = malloc(sizeof (int) * 2);
  152. res[WIDTH] = 0;
  153. res[HEIGHT] = 1;
  154. //Parcours la 1er ligne pour compter le nombre de caractère
  155. while (*map != '\n' && *map != '\0') {
  156. res[WIDTH]++;
  157. map++;
  158. }
  159. if (*map == '\0') {
  160. return res;
  161. }
  162. //Compte les lignes
  163. map++;
  164. while (*map != '\0') {
  165. if (*map == '\n') {
  166. res[HEIGHT]++;
  167. }
  168. map++;
  169. }
  170. return res;
  171. }
  172. int create_game(char* name, char* map) {
  173. int length, index = 0;
  174. char* path;
  175. int* size;
  176. //Regarde si il reste une game de disponnible
  177. if (nbGame == MAXGAME) {
  178. return ERR;
  179. }
  180. //Cherche une game libre
  181. while (index < MAXGAME) {
  182. pthread_mutex_lock(&gameMutex[index]);
  183. if (game[index].active == false) {
  184. break;
  185. }
  186. pthread_mutex_unlock(&gameMutex[index]);
  187. index++;
  188. }
  189. //Recup la map
  190. length = strlen(MAPDIR) + strlen(map);
  191. path = new_string(length);
  192. snprintf(path, length + 1, "%s%s", MAPDIR, map);
  193. game[index].mapContent = file_get_content(path);
  194. //Calcul taille de la map
  195. size = map_size(game[index].mapContent);
  196. //Set Up
  197. game[index].active = true;
  198. game[index].name = string_copy(name);
  199. game[index].nbPlayer = 0;
  200. game[index].mapName = string_copy(map);
  201. game[index].width = size[WIDTH];
  202. game[index].height = size[HEIGHT];
  203. game[index].map = parse_map(game[index].mapContent, size[WIDTH], size[HEIGHT]);
  204. for (int i = 0; i < MAXPLAYER; i++) {
  205. game[index].player[i] = malloc(sizeof (Player));
  206. game[index].player[i]->ini = false;
  207. }
  208. game[index].object = malloc(sizeof (Object));
  209. object_ini(game[index].object);
  210. //object_add(game[index].object, OBJ_MAJOR, 1, 1);
  211. pthread_mutex_unlock(&gameMutex[index]);
  212. //Retourne la position de la partie dans le tableau
  213. nbGame++;
  214. free(path);
  215. free(size);
  216. return index;
  217. }
  218. int add_player(Game* g, int cliId) {
  219. int index = 0;
  220. Client* cli;
  221. //Verif que la game n'est pas deja pleine
  222. pthread_mutex_lock(&gameMutex[g->index]);
  223. if (g->nbPlayer >= MAXPLAYER) {
  224. pthread_mutex_unlock(&gameMutex[g->index]);
  225. return ERR;
  226. }
  227. //Cherche un joueur non initialisé
  228. while (index < MAXPLAYER) {
  229. pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
  230. if (!g->player[index]->ini) {
  231. break;
  232. }
  233. pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
  234. index++;
  235. }
  236. //Recup du client
  237. cli = get_client(cliId);
  238. if (cli == NULL) {
  239. pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
  240. pthread_mutex_unlock(&gameMutex[g->index]);
  241. return ERR;
  242. }
  243. //Creation du joueur
  244. create_player(g->player[index], cli);
  245. g->nbPlayer++;
  246. pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
  247. pthread_mutex_unlock(&gameMutex[g->index]);
  248. return index;
  249. }
  250. void describe_game(Game* g, int playerIndex, JsonEncoder* desc) {
  251. JsonEncoder player;
  252. JsonEncoder map;
  253. JsonArray players;
  254. char* content;
  255. //Initialisation
  256. ini_encoder(&player);
  257. ini_encoder(&map);
  258. ini_array_encoder(&players);
  259. //Info map
  260. pthread_mutex_lock(&gameMutex[g->index]);
  261. content = remove_char(g->mapContent, '\n'); //La map sans \n car interdit en JSON
  262. add_integer(&map, "width", g->width);
  263. add_integer(&map, "height", g->height);
  264. add_string(&map, "content", content);
  265. free(content);
  266. //Ajout info
  267. add_integer(desc, "nbPlayers", g->nbPlayer);
  268. add_object(desc, "map", &map);
  269. //Ajout info courte joueur
  270. //printf("Add players\n");
  271. for (int i = 0; i < MAXPLAYER; i++) {
  272. pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + i]);
  273. if (g->player[i]->ini) {
  274. describe_short_player(g->player[i], &player);
  275. add_array_object(&players, &player);
  276. clean_json_encoder(&player);
  277. }
  278. pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + i]);
  279. }
  280. //printf("Fin Add players\n");
  281. add_array(desc, "players", &players);
  282. //Si besoins ajout un joueur
  283. if (playerIndex >= 0 && playerIndex < MAXPLAYER) {
  284. pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
  285. if (g->player[playerIndex]->ini) {
  286. describe_player(g->player[playerIndex], &player);
  287. add_object(desc, "player", &player);
  288. clean_json_encoder(&player);
  289. }
  290. pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
  291. }
  292. //Nettoyage
  293. pthread_mutex_unlock(&gameMutex[g->index]);
  294. clean_json_encoder(&map);
  295. clean_json_array(&players);
  296. }
  297. boolean notify_player(Game* g, char* method, char* ressource, JsonEncoder* param, int excludePlayerId) {
  298. boolean res = true;
  299. pthread_mutex_lock(&gameMutex[g->index]);
  300. //Regarde si la game est active
  301. if (!g->active) {
  302. pthread_mutex_unlock(&gameMutex[g->index]);
  303. return false;
  304. }
  305. //Parcours les joeurs de la game
  306. for (int i = 0; i < MAXPLAYER; i++) {
  307. //Si joueur actif
  308. pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + i]);
  309. if (g->player[i]->ini && g->player[i]->id != excludePlayerId) {
  310. res = res && notify_client(g->player[i]->cli, method, ressource, param);
  311. }
  312. pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + i]);
  313. }
  314. pthread_mutex_unlock(&gameMutex[g->index]);
  315. return res;
  316. }
  317. boolean player_collision(Game* g, int x, int y) {
  318. for (int i = 0; i < MAXPLAYER; i++) {
  319. if (g->player[i]->ini) {
  320. if (g->player[i]->x == x && g->player[i]->y == y) {
  321. return true;
  322. }
  323. }
  324. }
  325. return false;
  326. }
  327. boolean player_collision_index(Game* g, int x, int y, int* index) {
  328. for (int i = 0; i < MAXPLAYER; i++) {
  329. if (g->player[i]->ini) {
  330. if (g->player[i]->x == x && g->player[i]->y == y) {
  331. *index = i;
  332. return true;
  333. }
  334. }
  335. }
  336. return false;
  337. }
  338. boolean bomb_explode(Game* g, int playerIndex, int x, int y, JsonEncoder* json) {
  339. JsonEncoder object, notif, coord;
  340. JsonArray bomb, bonus, chain, explosion;
  341. int res, index, cBomb = 0, cBonus = 0, cChain = 0;
  342. obj_node* objn;
  343. //Inie json
  344. ini_encoder(&object);
  345. ini_encoder(&notif);
  346. ini_encoder(&coord);
  347. ini_array_encoder(&bomb);
  348. ini_array_encoder(&bonus);
  349. ini_array_encoder(&chain);
  350. ini_array_encoder(&explosion);
  351. //Mutex
  352. pthread_mutex_lock(&gameMutex[g->index]);
  353. if (playerIndex >= 0) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
  354. //Determine le type de la bombe
  355. switch (g->map[x][y]) {
  356. case '1':
  357. add_string(json, "type", "classic");
  358. g->player[playerIndex]->classicBomb++;
  359. g->player[playerIndex]->nbBomb--;
  360. objn = object_search(g->player[playerIndex]->bomb, OBJ_BCLASSIC, x, y);
  361. object_delete(g->player[playerIndex]->bomb, objn);
  362. break;
  363. case '2':
  364. add_string(json, "type", "mine");
  365. g->player[playerIndex]->mine++;
  366. g->player[playerIndex]->nbBomb--;
  367. objn = object_search(g->player[playerIndex]->bomb, OBJ_BMINE, x, y);
  368. object_delete(g->player[playerIndex]->bomb, objn);
  369. break;
  370. case '3':
  371. add_string(json, "type", "remote");
  372. g->player[playerIndex]->remoteBomb++;
  373. g->player[playerIndex]->nbBomb--;
  374. objn = object_search(g->player[playerIndex]->bomb, OBJ_BREMOTE, x, y);
  375. object_delete(g->player[playerIndex]->bomb, objn);
  376. break;
  377. default:
  378. if (playerIndex >= 0) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
  379. pthread_mutex_unlock(&gameMutex[g->index]);
  380. return false;
  381. }
  382. //Determine la position de la bombe
  383. char pos[20];
  384. memset(pos, 0, 20);
  385. snprintf(pos, 20, "%d,%d", x, y);
  386. add_string(json, "pos", pos);
  387. //Ajoute coord explosion
  388. add_integer(&coord, "x", x);
  389. add_integer(&coord, "y", y);
  390. add_array_object(&explosion, &coord);
  391. clean_json_encoder(&coord);
  392. //Calcul l'explosion non mine
  393. if (g->map[x][y] != '2') {
  394. g->map[x][y] = '_';
  395. //Si le joueur à un bonus
  396. if (g->player[playerIndex]->firePower > 0) {
  397. add_boolean(json, "bonus", true);
  398. } else {
  399. add_boolean(json, "bonus", false);
  400. }
  401. //Vers le haut
  402. for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
  403. //Si on est dans la map
  404. if (y - 1 - i >= 0) {
  405. //Si un mur destructible
  406. if (g->map[x][y - 1 - i] == '*') {
  407. g->map[x][y - 1 - i] = '_';
  408. res = spawn_object(g, x, y - 1 - i, &object);
  409. if (res == 1) { //Bombe
  410. cBomb++;
  411. add_array_object(&bomb, &object);
  412. clean_json_encoder(&object);
  413. } else if (res == 2) { //Bonus Malus
  414. cBonus++;
  415. add_array_object(&bonus, &object);
  416. clean_json_encoder(&object);
  417. }
  418. //Ajoute coord explosion
  419. add_integer(&coord, "x", x);
  420. add_integer(&coord, "y", y - 1 - i);
  421. add_array_object(&explosion, &coord);
  422. clean_json_encoder(&coord);
  423. break;
  424. }
  425. //Si un joueur
  426. if (player_collision_index(g, x, y - 1 - i, &index)) {
  427. if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
  428. if (g->player[index]->major == 0) {
  429. //Baisse la vie
  430. g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
  431. //Notification du joueur
  432. describe_player(g->player[index], &notif);
  433. if (!notify_client(g->player[index]->cli, "POST", "attack/affect", &notif)) {
  434. adderror("Impossible de notifer le client");
  435. }
  436. clean_json_encoder(&notif);
  437. }
  438. if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
  439. }
  440. //Si une bombe
  441. if (g->map[x][y - 1 - i] == '1' || g->map[x][y - 1 - i] == '2' || g->map[x][y - 1 - i] == '3') {
  442. cChain++;
  443. bomb_chain(g, playerIndex, x, y - 1 - i, &chain, &explosion);
  444. }
  445. //Si un mur solide
  446. if (g->map[x][y - 1 - i] == '-') {
  447. break;
  448. }
  449. //Ajoute coord explosion
  450. add_integer(&coord, "x", x);
  451. add_integer(&coord, "y", y - 1 - i);
  452. add_array_object(&explosion, &coord);
  453. clean_json_encoder(&coord);
  454. } else {
  455. break;
  456. }
  457. }
  458. //Vers le bas
  459. for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
  460. //Si on est dans la map
  461. if (y + 1 + i <= g->height) {
  462. //Si un mur destructible
  463. if (g->map[x][y + 1 + i] == '*') {
  464. g->map[x][y + 1 + i] = '_';
  465. res = spawn_object(g, x, y + 1 + i, &object);
  466. if (res == 1) { //Bombe
  467. cBomb++;
  468. add_array_object(&bomb, &object);
  469. clean_json_encoder(&object);
  470. } else if (res == 2) { //Bonus Malus
  471. cBonus++;
  472. add_array_object(&bonus, &object);
  473. clean_json_encoder(&object);
  474. }
  475. //Ajoute coord explosion
  476. add_integer(&coord, "x", x);
  477. add_integer(&coord, "y", y + 1 + i);
  478. add_array_object(&explosion, &coord);
  479. clean_json_encoder(&coord);
  480. break;
  481. }
  482. //Si un joueur
  483. if (player_collision_index(g, x, y + 1 + i, &index)) {
  484. if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
  485. if (g->player[index]->major == 0) {
  486. //Baisse la vie
  487. g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
  488. //Notification du joueur
  489. describe_player(g->player[index], &notif);
  490. if (!notify_client(g->player[index]->cli, "POST", "attack/affect", &notif)) {
  491. adderror("Impossible de notifer le client");
  492. }
  493. clean_json_encoder(&notif);
  494. }
  495. if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
  496. }
  497. //Si une bombe
  498. if (g->map[x][y + 1 + i] == '1' || g->map[x][y + 1 + i] == '2' || g->map[x][y + 1 + i] == '3') {
  499. cChain++;
  500. bomb_chain(g, playerIndex, x, y + 1 + i, &chain, &explosion);
  501. }
  502. //Si un mur solide
  503. if (g->map[x][y + 1 + i] == '-') {
  504. break;
  505. }
  506. //Ajoute coord explosion
  507. add_integer(&coord, "x", x);
  508. add_integer(&coord, "y", y + 1 + i);
  509. add_array_object(&explosion, &coord);
  510. clean_json_encoder(&coord);
  511. } else {
  512. break;
  513. }
  514. }
  515. //Vers la gauche
  516. for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
  517. //Si on est dans la map
  518. if (x - 1 - i >= 0) {
  519. //Si un mur destructible
  520. if (g->map[x - 1 - i][y] == '*') {
  521. g->map[x - 1 - i][y] = '_';
  522. res = spawn_object(g, x - 1 - i, y, &object);
  523. if (res == 1) { //Bombe
  524. cBomb++;
  525. add_array_object(&bomb, &object);
  526. clean_json_encoder(&object);
  527. } else if (res == 2) { //Bonus Malus
  528. cBonus++;
  529. add_array_object(&bonus, &object);
  530. clean_json_encoder(&object);
  531. }
  532. //Ajoute coord explosion
  533. add_integer(&coord, "x", x - 1 - i);
  534. add_integer(&coord, "y", y);
  535. add_array_object(&explosion, &coord);
  536. clean_json_encoder(&coord);
  537. break;
  538. }
  539. //Si un joueur
  540. if (player_collision_index(g, x - 1 - i, y, &index)) {
  541. if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
  542. if (g->player[index]->major == 0) {
  543. //Baisse la vie
  544. g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
  545. //Notification du joueur
  546. describe_player(g->player[index], &notif);
  547. if (!notify_client(g->player[index]->cli, "POST", "attack/affect", &notif)) {
  548. adderror("Impossible de notifer le client");
  549. }
  550. clean_json_encoder(&notif);
  551. }
  552. if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
  553. }
  554. //Si une bombe
  555. if (g->map[x - 1 - i][y] == '1' || g->map[x - 1 - i][y] == '2' || g->map[x - 1 - i][y] == '3') {
  556. cChain++;
  557. bomb_chain(g, playerIndex, x - 1 - i, y, &chain, &explosion);
  558. }
  559. //Si un mur solide
  560. if (g->map[x - 1 - i][y] == '-') {
  561. break;
  562. }
  563. //Ajoute coord explosion
  564. add_integer(&coord, "x", x - 1 - i);
  565. add_integer(&coord, "y", y);
  566. add_array_object(&explosion, &coord);
  567. clean_json_encoder(&coord);
  568. } else {
  569. break;
  570. }
  571. }
  572. //Vers la droite
  573. for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
  574. //Si on est dans la map
  575. if (x + 1 + i >= 0) {
  576. //Si un mur destructible
  577. if (g->map[x + 1 + i][y] == '*') {
  578. g->map[x + 1 + i][y] = '_';
  579. res = spawn_object(g, x + 1 + i, y, &object);
  580. if (res == 1) { //Bombe
  581. cBomb++;
  582. add_array_object(&bomb, &object);
  583. clean_json_encoder(&object);
  584. } else if (res == 2) { //Bonus Malus
  585. cBonus++;
  586. add_array_object(&bonus, &object);
  587. clean_json_encoder(&object);
  588. }
  589. //Ajoute coord explosion
  590. add_integer(&coord, "x", x + 1 + i);
  591. add_integer(&coord, "y", y);
  592. add_array_object(&explosion, &coord);
  593. clean_json_encoder(&coord);
  594. break;
  595. }
  596. //Si un joueur
  597. if (player_collision_index(g, x + 1 + i, y, &index)) {
  598. if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
  599. if (g->player[index]->major == 0) {
  600. //Baisse la vie
  601. g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
  602. //Notification du joueur
  603. describe_player(g->player[index], &notif);
  604. if (!notify_client(g->player[index]->cli, "POST", "attack/affect", &notif)) {
  605. adderror("Impossible de notifer le client");
  606. }
  607. clean_json_encoder(&notif);
  608. }
  609. if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
  610. }
  611. //Si une bombe
  612. if (g->map[x + 1 + i][y] == '1' || g->map[x + 1 + i][y] == '2' || g->map[x + 1 + i][y] == '3') {
  613. cChain++;
  614. bomb_chain(g, playerIndex, x + 1 + i, y, &chain, &explosion);
  615. }
  616. //Si un mur solide
  617. if (g->map[x + 1 + i][y] == '-') {
  618. break;
  619. }
  620. //Ajoute coord explosion
  621. add_integer(&coord, "x", x + 1 + i);
  622. add_integer(&coord, "y", y);
  623. add_array_object(&explosion, &coord);
  624. clean_json_encoder(&coord);
  625. } else {
  626. break;
  627. }
  628. }
  629. }//Si c'est une mine
  630. else {
  631. g->map[x][y] = '_';
  632. //Calcul dommage
  633. if (g->player[playerIndex]->major == 0) {
  634. //Baisse la vie
  635. g->player[playerIndex]->life = g->player[playerIndex]->life - (g->player[playerIndex]->maxLife * DAMAGEMINE);
  636. //Notification du joueur
  637. describe_player(g->player[playerIndex], &notif);
  638. if (!notify_client(g->player[playerIndex]->cli, "POST", "attack/affect", &notif)) {
  639. adderror("Impossible de notifer le client");
  640. }
  641. clean_json_encoder(&notif);
  642. }
  643. //Bas de bonus si mine
  644. add_boolean(json, "bonus", false);
  645. }
  646. //Affichage de la map
  647. free(g->mapContent);
  648. g->mapContent = unparse_map(g->map, g->width, g->height);
  649. add_string(json, "map", g->mapContent);
  650. //Ajout des json
  651. add_array(json, "bomb", &bomb);
  652. add_array(json, "bonusMalus", &bonus);
  653. add_array(json, "chain", &chain);
  654. add_array(json, "explosion", &explosion);
  655. //Nettoyage
  656. if (playerIndex >= 0) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
  657. pthread_mutex_unlock(&gameMutex[g->index]);
  658. clean_json_array(&bomb);
  659. clean_json_array(&bonus);
  660. clean_json_array(&chain);
  661. clean_json_array(&explosion);
  662. return true;
  663. }
  664. void bomb_chain(Game* g, int playerIndex, int x, int y, JsonArray* chain, JsonArray* explosion) {
  665. JsonEncoder json, notif, coord;
  666. int index;
  667. Player* p;
  668. obj_node* objn = NULL;
  669. //Inie json
  670. ini_encoder(&json);
  671. ini_encoder(&notif);
  672. ini_encoder(&coord);
  673. //Determine le type de la bombe
  674. switch (g->map[x][y]) {
  675. case '1':
  676. add_string(&json, "type", "classic");
  677. p = search_player_object(g, OBJ_BCLASSIC, x, y);
  678. if (p != NULL) {
  679. p->classicBomb++;
  680. p->nbBomb--;
  681. objn = object_search(p->bomb, OBJ_BCLASSIC, x, y);
  682. object_delete(p->bomb, objn);
  683. }
  684. break;
  685. case '2':
  686. add_string(&json, "type", "mine");
  687. p = search_player_object(g, OBJ_BMINE, x, y);
  688. if (p != NULL) {
  689. p->mine++;
  690. p->nbBomb--;
  691. objn = object_search(p->bomb, OBJ_BMINE, x, y);
  692. object_delete(p->bomb, objn);
  693. }
  694. break;
  695. case '3':
  696. add_string(&json, "type", "remote");
  697. p = search_player_object(g, OBJ_BREMOTE, x, y);
  698. if (p != NULL) {
  699. p->remoteBomb++;
  700. p->nbBomb--;
  701. objn = object_search(p->bomb, OBJ_BREMOTE, x, y);
  702. object_delete(p->bomb, objn);
  703. }
  704. break;
  705. default:
  706. return;
  707. }
  708. //Determine la position de la bombe
  709. char pos[20];
  710. memset(pos, 0, 20);
  711. snprintf(pos, 20, "%d,%d", x, y);
  712. add_string(&json, "pos", pos);
  713. //Calcul l'explosion non mine
  714. if (g->map[x][y] != '2') {
  715. g->map[x][y] = '_';
  716. //Vers le haut
  717. for (int i = 0; i < 2; i++) {
  718. //Si on est dans la map
  719. if (y - 1 - i >= 0) {
  720. //Si un mur destructible
  721. if (g->map[x][y - 1 - i] == '*') {
  722. g->map[x][y - 1 - i] = '_';
  723. //Ajoute coord explosion
  724. add_integer(&coord, "x", x);
  725. add_integer(&coord, "y", y - 1 - i);
  726. add_array_object(explosion, &coord);
  727. clean_json_encoder(&coord);
  728. break;
  729. }
  730. //Si un joueur
  731. if (player_collision_index(g, x, y - 1 - i, &index)) {
  732. if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
  733. if (g->player[index]->major == 0) {
  734. //Baisse la vie
  735. g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
  736. //Notification du joueur
  737. describe_player(g->player[index], &notif);
  738. if (!notify_client(g->player[index]->cli, "POST", "attack/affect", &notif)) {
  739. adderror("Impossible de notifer le client");
  740. }
  741. clean_json_encoder(&notif);
  742. }
  743. if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
  744. }
  745. //Si une bombe
  746. if (g->map[x][y - 1 - i] == '1' || g->map[x][y - 1 - i] == '2' || g->map[x][y - 1 - i] == '3') {
  747. bomb_chain(g, playerIndex, x, y - 1 - i, chain, explosion);
  748. }
  749. //Si un mur solide
  750. if (g->map[x][y - 1 - i] == '-') {
  751. break;
  752. }
  753. //Ajoute coord explosion
  754. add_integer(&coord, "x", x);
  755. add_integer(&coord, "y", y - 1 - i);
  756. add_array_object(explosion, &coord);
  757. clean_json_encoder(&coord);
  758. } else {
  759. break;
  760. }
  761. }
  762. //Vers le bas
  763. for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
  764. //Si on est dans la map
  765. if (y + 1 + i <= g->height) {
  766. //Si un mur destructible
  767. if (g->map[x][y + 1 + i] == '*') {
  768. g->map[x][y + 1 + i] = '_';
  769. //Ajoute coord explosion
  770. add_integer(&coord, "x", x);
  771. add_integer(&coord, "y", y + 1 + i);
  772. add_array_object(explosion, &coord);
  773. clean_json_encoder(&coord);
  774. break;
  775. }
  776. //Si un joueur
  777. if (player_collision_index(g, x, y + 1 + i, &index)) {
  778. if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
  779. if (g->player[index]->major == 0) {
  780. //Baisse la vie
  781. g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
  782. //Notification du joueur
  783. describe_player(g->player[index], &notif);
  784. if (!notify_client(g->player[index]->cli, "POST", "attack/affect", &notif)) {
  785. adderror("Impossible de notifer le client");
  786. }
  787. clean_json_encoder(&notif);
  788. }
  789. if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
  790. }
  791. //Si une bombe
  792. if (g->map[x][y + 1 + i] == '1' || g->map[x][y + 1 + i] == '2' || g->map[x][y + 1 + i] == '3') {
  793. bomb_chain(g, playerIndex, x, y + 1 + i, chain, explosion);
  794. }
  795. //Si un mur solide
  796. if (g->map[x][y + 1 + i] == '-') {
  797. break;
  798. }
  799. //Ajoute coord explosion
  800. add_integer(&coord, "x", x);
  801. add_integer(&coord, "y", y + 1 + i);
  802. add_array_object(explosion, &coord);
  803. clean_json_encoder(&coord);
  804. } else {
  805. break;
  806. }
  807. }
  808. //Vers la gauche
  809. for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
  810. //Si on est dans la map
  811. if (x - 1 - i >= 0) {
  812. //Si un mur destructible
  813. if (g->map[x - 1 - i][y] == '*') {
  814. g->map[x - 1 - i][y] = '_';
  815. //Ajoute coord explosion
  816. add_integer(&coord, "x", x - 1 - i);
  817. add_integer(&coord, "y", y);
  818. add_array_object(explosion, &coord);
  819. clean_json_encoder(&coord);
  820. break;
  821. }
  822. //Si un joueur
  823. if (player_collision_index(g, x - 1 - i, y, &index)) {
  824. if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
  825. if (g->player[index]->major == 0) {
  826. //Baisse la vie
  827. g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
  828. //Notification du joueur
  829. describe_player(g->player[index], &notif);
  830. if (!notify_client(g->player[index]->cli, "POST", "attack/affect", &notif)) {
  831. adderror("Impossible de notifer le client");
  832. }
  833. clean_json_encoder(&notif);
  834. }
  835. if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
  836. }
  837. //Si une bombe
  838. if (g->map[x - 1 - i][y] == '1' || g->map[x - 1 - i][y] == '2' || g->map[x - 1 - i][y] == '3') {
  839. bomb_chain(g, playerIndex, x - 1 - i, y, chain, explosion);
  840. }
  841. //Si un mur solide
  842. if (g->map[x - 1 - i][y] == '-') {
  843. break;
  844. }
  845. //Ajoute coord explosion
  846. add_integer(&coord, "x", x - 1 - i);
  847. add_integer(&coord, "y", y);
  848. add_array_object(explosion, &coord);
  849. clean_json_encoder(&coord);
  850. } else {
  851. break;
  852. }
  853. }
  854. //Vers la droite
  855. for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
  856. //Si on est dans la map
  857. if (x + 1 + i >= 0) {
  858. //Si un mur destructible
  859. if (g->map[x + 1 + i][y] == '*') {
  860. g->map[x + 1 + i][y] = '_';
  861. //Ajoute coord explosion
  862. add_integer(&coord, "x", x + 1 + i);
  863. add_integer(&coord, "y", y);
  864. add_array_object(explosion, &coord);
  865. clean_json_encoder(&coord);
  866. break;
  867. }
  868. //Si un joueur
  869. if (player_collision_index(g, x + 1 + i, y, &index)) {
  870. if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
  871. if (g->player[index]->major == 0) {
  872. //Baisse la vie
  873. g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
  874. //Notification du joueur
  875. describe_player(g->player[index], &notif);
  876. if (!notify_client(g->player[index]->cli, "POST", "attack/affect", &notif)) {
  877. adderror("Impossible de notifer le client");
  878. }
  879. clean_json_encoder(&notif);
  880. }
  881. if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
  882. }
  883. //Si une bombe
  884. if (g->map[x + 1 + i][y] == '1' || g->map[x + 1 + i][y] == '2' || g->map[x + 1 + i][y] == '3') {
  885. bomb_chain(g, playerIndex, x + 1 + i, y, chain, explosion);
  886. }
  887. //Si un mur solide
  888. if (g->map[x + 1 + i][y] == '-') {
  889. break;
  890. }
  891. //Ajoute coord explosion
  892. add_integer(&coord, "x", x + 1 + i);
  893. add_integer(&coord, "y", y);
  894. add_array_object(explosion, &coord);
  895. clean_json_encoder(&coord);
  896. } else {
  897. break;
  898. }
  899. }
  900. }//Si c'est une mine
  901. else {
  902. g->map[x][y] = '_';
  903. //Recup le joueur
  904. if (player_collision_index(g, x, y, &index)) {
  905. if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
  906. if (g->player[index]->major == 0) {
  907. //Baisse la vie
  908. g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * DAMAGEMINE);
  909. //Notification du joueur
  910. describe_player(g->player[index], &notif);
  911. if (!notify_client(g->player[index]->cli, "POST", "attack/affect", &notif)) {
  912. adderror("Impossible de notifer le client");
  913. }
  914. clean_json_encoder(&notif);
  915. }
  916. if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
  917. }
  918. }
  919. //Ajoute json dans le tableau
  920. add_array_object(chain, &json);
  921. //Nettoyage
  922. clean_json_encoder(&json);
  923. }
  924. int spawn_object(Game* g, int x, int y, JsonEncoder* json) {
  925. int random, res = 0;
  926. //Generation random si spawn ou non
  927. srand(time(NULL));
  928. random = rand() % 100 + 1;
  929. if (random > SPAWNRATE) {
  930. return 0; //Pas de spawn
  931. }
  932. //Choisit l'objet
  933. random = rand() % 11;
  934. switch (random) {
  935. case OBJ_BCLASSIC:
  936. res = 1;
  937. add_string(json, "type", "classic");
  938. break;
  939. case OBJ_BMINE:
  940. res = 1;
  941. add_string(json, "type", "mine");
  942. break;
  943. case OBJ_BREMOTE:
  944. res = 1;
  945. add_string(json, "type", "remote");
  946. break;
  947. case OBJ_BOMBUP:
  948. res = 2;
  949. add_string(json, "type", "bomb_up");
  950. break;
  951. case OBJ_BOMBDOWN:
  952. res = 2;
  953. add_string(json, "type", "bomb_down");
  954. break;
  955. case OBJ_FIREPOWER:
  956. res = 2;
  957. add_string(json, "type", "fire_power");
  958. break;
  959. case OBJ_SCOOTER:
  960. res = 2;
  961. add_string(json, "type", "scooter");
  962. break;
  963. case OBJ_BROKENLEG:
  964. res = 2;
  965. add_string(json, "type", "broken_legs");
  966. break;
  967. case OBJ_LIFEUP:
  968. res = 2;
  969. add_string(json, "type", "life_up");
  970. break;
  971. case OBJ_LIFEMAX:
  972. res = 2;
  973. add_string(json, "type", "life_max");
  974. break;
  975. case OBJ_MAJOR:
  976. res = 2;
  977. add_string(json, "type", "major");
  978. break;
  979. }
  980. //Ajoute l'objet dans la partie
  981. object_add(g->object, random, x, y);
  982. //Ajoute postion au json
  983. char pos[20];
  984. memset(pos, 0, 20);
  985. snprintf(pos, 20, "%d,%d", x, y);
  986. add_string(json, "pos", pos);
  987. //Retourne type d'ajout
  988. return res;
  989. }
  990. void remove_player(Game* g, int playerIndex) {
  991. pthread_mutex_lock(&gameMutex[g->index]);
  992. pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
  993. g->nbPlayer--;
  994. delete_player(g->player[playerIndex]);
  995. pthread_mutex_unlock(&gameMutex[g->index]);
  996. pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
  997. }
  998. void stop_game(Game* g) {
  999. pthread_mutex_lock(&gameMutex[g->index]);
  1000. //Indique comme inactive
  1001. g->active = false;
  1002. //Suppr les joueurs
  1003. for (int i = 0; i < MAXPLAYER; i++) {
  1004. //pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + i]);
  1005. if (g->player[i]->ini) {
  1006. delete_player(g->player[i]);
  1007. }
  1008. free(g->player[i]);
  1009. //pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + i]);
  1010. }
  1011. //Libere la memoire
  1012. object_clean(g->object);
  1013. free(g->object);
  1014. for (int i = 0; i < g->width; i++) {
  1015. free(g->map[i]);
  1016. }
  1017. free(g->map);
  1018. free(g->mapName);
  1019. free(g->mapContent);
  1020. pthread_mutex_unlock(&gameMutex[g->index]);
  1021. //Retire une game
  1022. nbGame--;
  1023. }
  1024. void clean_games() {
  1025. for (int i = 0; i < MAXGAME; i++) {
  1026. if (game[i].active) {
  1027. pthread_mutex_unlock(&gameMutex[i]);
  1028. stop_game(&game[i]);
  1029. }
  1030. }
  1031. }