123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053 |
- /*
- * File: game.c
- * Author: Arthur Brandao
- *
- * Created on 28 novembre 2018
- */
- #define _XOPEN_SOURCE 500
- #include <stdio.h>
- #include <stdlib.h>
- #include "error.h"
- #include "str.h"
- #include "file.h"
- #include "game.h"
- #include "bomberstudent_server.h"
- /* --- Extern --- */
- Game game[MAXGAME];
- int nbGame = 0;
- pthread_mutex_t gameMutex[MAXGAME];
- pthread_mutex_t playerMutex[MAXGAME * MAXPLAYER];
- /* --- Fonctions privées --- */
- /**
- * Transforme le fichier map en un tableau 2D
- * @param char* Le contenu du fichier map
- * @param int Largeur de la map
- * @param int Hauteur de la map
- * @return char** La map parser
- */
- char** parse_map(char* mapContent, int width, int height) {
- char** map = malloc(sizeof (char*) * width);
- //Creation des colonnes
- for (int i = 0; i < width; i++) {
- map[i] = malloc(sizeof (char) * height);
- }
- //Remplissage
- for (int i = 0; i < height; i++) {
- for (int j = 0; j < width; j++) {
- map[j][i] = *mapContent;
- mapContent++;
- }
- mapContent++;
- }
- return map;
- }
- /**
- * Transforme un tableau 2D en une chaine
- * @param char** Le contenu du fichier map
- * @param int Largeur de la map
- * @param int Hauteur de la map
- * @return char* La map
- */
- char* unparse_map(char** map, int width, int height) {
- int pos = 0;
- char* mapContent = malloc(sizeof (char) * (width * height + 1));
- memset(mapContent, 0, width * height + 1);
- //Remplissage
- for (int i = 0; i < height; i++) {
- for (int j = 0; j < width; j++) {
- mapContent[pos++] = map[j][i];
- }
- }
- return mapContent;
- }
- /**
- * Cherche le joueur à qui appartient un objet
- * @param Game* La game du joueur
- * @param int Le type de l'objet
- * @param int X de l'objet
- * @param int Y de l'objet
- * @return Player* Le joueur trouvé ou NULL
- */
- Player* search_player_object(Game* g, int type, int x, int y) {
- obj_node* objn;
- for (int i = 0; i < MAXPLAYER; i++) {
- if (g->player[i]->ini) {
- objn = object_search(g->player[i]->bomb, type, x, y);
- if (objn != NULL) {
- return g->player[i];
- }
- }
- }
- return NULL;
- }
- /* --- Fonctions publiques --- */
- boolean ini_games() {
- //Ini les games
- for (int i = 0; i < MAXGAME; i++) {
- game[i].active = false;
- game[i].index = i;
- }
- //Ini les mutex des games
- for (int i = 0; i < MAXGAME; i++) {
- if (pthread_mutex_init(&gameMutex[i], NULL) != 0) {
- adderror("Impossible d'initialiser les mutex des games");
- return false;
- }
- }
- //Ini les mutex des joueurs des games
- for (int i = 0; i < MAXGAME * MAXPLAYER; i++) {
- if (pthread_mutex_init(&playerMutex[i], NULL) != 0) {
- adderror("Impossible d'initialiser les mutex des joueurs");
- return false;
- }
- }
- return true;
- }
- void list_map(JsonArray* res) {
- char** result;
- int nbResult;
- //Regarde les fichiers dans le dossier
- result = file_list(MAPDIR, &nbResult);
- for (int i = 0; i < nbResult; i++) {
- add_array_string(res, result[i]);
- free(result[i]);
- }
- free(result);
- }
- int list_game(JsonArray* res) {
- JsonEncoder gameJson;
- int compteur = 0, i = 0;
- //Si il n' y a aucune game
- if (nbGame == 0) {
- return 0;
- }
- //Initialisation json
- ini_encoder(&gameJson);
- //Ajoute chaque game
- while (compteur < nbGame && i < MAXGAME) {
- pthread_mutex_lock(&gameMutex[i]);
- if (!game[i].active) {
- pthread_mutex_unlock(&gameMutex[i]);
- i++;
- continue;
- }
- //Creation objet json
- add_string(&gameJson, "name", game[i].name);
- add_integer(&gameJson, "nbPlayer", game[i].nbPlayer);
- add_string(&gameJson, "map", game[i].mapName);
- //Ajout dans le tableau
- add_array_object(res, &gameJson);
- //Nettoyage encoder objet
- clean_json_encoder(&gameJson);
- //Incremente
- pthread_mutex_unlock(&gameMutex[i]);
- i++;
- compteur++;
- }
- return nbGame;
- }
- int* map_size(char* map) {
- int* res;
- res = malloc(sizeof (int) * 2);
- res[WIDTH] = 0;
- res[HEIGHT] = 1;
- //Parcours la 1er ligne pour compter le nombre de caractère
- while (*map != '\n' && *map != '\0') {
- res[WIDTH]++;
- map++;
- }
- if (*map == '\0') {
- return res;
- }
- //Compte les lignes
- map++;
- while (*map != '\0') {
- if (*map == '\n') {
- res[HEIGHT]++;
- }
- map++;
- }
- return res;
- }
- int create_game(char* name, char* map) {
- int length, index = 0;
- char* path;
- int* size;
- //Regarde si il reste une game de disponnible
- if (nbGame == MAXGAME) {
- return ERR;
- }
- //Cherche une game libre
- while (index < MAXGAME) {
- pthread_mutex_lock(&gameMutex[index]);
- if (game[index].active == false) {
- break;
- }
- pthread_mutex_unlock(&gameMutex[index]);
- index++;
- }
- //Recup la map
- length = strlen(MAPDIR) + strlen(map);
- path = new_string(length);
- snprintf(path, length + 1, "%s%s", MAPDIR, map);
- game[index].mapContent = file_get_content(path);
- //Calcul taille de la map
- size = map_size(game[index].mapContent);
- //Set Up
- game[index].active = true;
- game[index].name = string_copy(name);
- game[index].nbPlayer = 0;
- game[index].mapName = string_copy(map);
- game[index].width = size[WIDTH];
- game[index].height = size[HEIGHT];
- game[index].map = parse_map(game[index].mapContent, size[WIDTH], size[HEIGHT]);
- for (int i = 0; i < MAXPLAYER; i++) {
- game[index].player[i] = malloc(sizeof (Player));
- game[index].player[i]->ini = false;
- }
- game[index].object = malloc(sizeof (Object));
- object_ini(game[index].object);
- //object_add(game[index].object, OBJ_MAJOR, 1, 1);
- pthread_mutex_unlock(&gameMutex[index]);
- //Retourne la position de la partie dans le tableau
- nbGame++;
- free(path);
- free(size);
- return index;
- }
- int add_player(Game* g, int cliId) {
- int index = 0;
- Client* cli;
- //Verif que la game n'est pas deja pleine
- pthread_mutex_lock(&gameMutex[g->index]);
- if (g->nbPlayer >= MAXPLAYER) {
- pthread_mutex_unlock(&gameMutex[g->index]);
- return ERR;
- }
- //Cherche un joueur non initialisé
- while (index < MAXPLAYER) {
- pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
- if (!g->player[index]->ini) {
- break;
- }
- pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
- index++;
- }
- //Recup du client
- cli = get_client(cliId);
- if (cli == NULL) {
- pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
- pthread_mutex_unlock(&gameMutex[g->index]);
- return ERR;
- }
- //Creation du joueur
- create_player(g->player[index], cli);
- g->nbPlayer++;
- pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
- pthread_mutex_unlock(&gameMutex[g->index]);
- return index;
- }
- void describe_game(Game* g, int playerIndex, JsonEncoder* desc) {
- JsonEncoder player;
- JsonEncoder map;
- JsonArray players;
- char* content;
- //Initialisation
- ini_encoder(&player);
- ini_encoder(&map);
- ini_array_encoder(&players);
- //Info map
- pthread_mutex_lock(&gameMutex[g->index]);
- content = remove_char(g->mapContent, '\n'); //La map sans \n car interdit en JSON
- add_integer(&map, "width", g->width);
- add_integer(&map, "height", g->height);
- add_string(&map, "content", content);
- free(content);
- //Ajout info
- add_integer(desc, "nbPlayers", g->nbPlayer);
- add_object(desc, "map", &map);
- //Ajout info courte joueur
- //printf("Add players\n");
- for (int i = 0; i < MAXPLAYER; i++) {
- pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + i]);
- if (g->player[i]->ini) {
- describe_short_player(g->player[i], &player);
- add_array_object(&players, &player);
- clean_json_encoder(&player);
- }
- pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + i]);
- }
- //printf("Fin Add players\n");
- add_array(desc, "players", &players);
- //Si besoins ajout un joueur
- if (playerIndex >= 0 && playerIndex < MAXPLAYER) {
- pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
- if (g->player[playerIndex]->ini) {
- describe_player(g->player[playerIndex], &player);
- add_object(desc, "player", &player);
- clean_json_encoder(&player);
- }
- pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
- }
- //Nettoyage
- pthread_mutex_unlock(&gameMutex[g->index]);
- clean_json_encoder(&map);
- clean_json_array(&players);
- }
- boolean notify_player(Game* g, char* method, char* ressource, JsonEncoder* param, int excludePlayerId) {
- boolean res = true;
- pthread_mutex_lock(&gameMutex[g->index]);
- //Regarde si la game est active
- if (!g->active) {
- pthread_mutex_unlock(&gameMutex[g->index]);
- return false;
- }
- //Parcours les joeurs de la game
- for (int i = 0; i < MAXPLAYER; i++) {
- //Si joueur actif
- pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + i]);
- if (g->player[i]->ini && g->player[i]->id != excludePlayerId) {
- res = res && notify_client(g->player[i]->cli, method, ressource, param);
- }
- pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + i]);
- }
- pthread_mutex_unlock(&gameMutex[g->index]);
- return res;
- }
- boolean player_collision(Game* g, int x, int y) {
- for (int i = 0; i < MAXPLAYER; i++) {
- if (g->player[i]->ini) {
- if (g->player[i]->x == x && g->player[i]->y == y) {
- return true;
- }
- }
- }
- return false;
- }
- boolean player_collision_index(Game* g, int x, int y, int* index) {
- for (int i = 0; i < MAXPLAYER; i++) {
- if (g->player[i]->ini) {
- if (g->player[i]->x == x && g->player[i]->y == y) {
- *index = i;
- return true;
- }
- }
- }
- return false;
- }
- boolean bomb_explode(Game* g, int playerIndex, int x, int y, JsonEncoder* json) {
- JsonEncoder object, notif, coord;
- JsonArray bomb, bonus, chain, explosion;
- int res, index, cBomb = 0, cBonus = 0, cChain = 0;
- obj_node* objn;
- //Inie json
- ini_encoder(&object);
- ini_encoder(¬if);
- ini_encoder(&coord);
- ini_array_encoder(&bomb);
- ini_array_encoder(&bonus);
- ini_array_encoder(&chain);
- ini_array_encoder(&explosion);
- //Mutex
- pthread_mutex_lock(&gameMutex[g->index]);
- if (playerIndex >= 0) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
- //Determine le type de la bombe
- switch (g->map[x][y]) {
- case '1':
- add_string(json, "type", "classic");
- g->player[playerIndex]->classicBomb++;
- g->player[playerIndex]->nbBomb--;
- objn = object_search(g->player[playerIndex]->bomb, OBJ_BCLASSIC, x, y);
- object_delete(g->player[playerIndex]->bomb, objn);
- break;
- case '2':
- add_string(json, "type", "mine");
- g->player[playerIndex]->mine++;
- g->player[playerIndex]->nbBomb--;
- objn = object_search(g->player[playerIndex]->bomb, OBJ_BMINE, x, y);
- object_delete(g->player[playerIndex]->bomb, objn);
- break;
- case '3':
- add_string(json, "type", "remote");
- g->player[playerIndex]->remoteBomb++;
- g->player[playerIndex]->nbBomb--;
- objn = object_search(g->player[playerIndex]->bomb, OBJ_BREMOTE, x, y);
- object_delete(g->player[playerIndex]->bomb, objn);
- break;
- default:
- if (playerIndex >= 0) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
- pthread_mutex_unlock(&gameMutex[g->index]);
- return false;
- }
- //Determine la position de la bombe
- char pos[20];
- memset(pos, 0, 20);
- snprintf(pos, 20, "%d,%d", x, y);
- add_string(json, "pos", pos);
- //Ajoute coord explosion
- add_integer(&coord, "x", x);
- add_integer(&coord, "y", y);
- add_array_object(&explosion, &coord);
- clean_json_encoder(&coord);
- //Calcul l'explosion non mine
- if (g->map[x][y] != '2') {
- g->map[x][y] = '_';
- //Si le joueur à un bonus
- if (g->player[playerIndex]->firePower > 0) {
- add_boolean(json, "bonus", true);
- } else {
- add_boolean(json, "bonus", false);
- }
- //Vers le haut
- for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
- //Si on est dans la map
- if (y - 1 - i >= 0) {
- //Si un mur destructible
- if (g->map[x][y - 1 - i] == '*') {
- g->map[x][y - 1 - i] = '_';
- res = spawn_object(g, x, y - 1 - i, &object);
- if (res == 1) { //Bombe
- cBomb++;
- add_array_object(&bomb, &object);
- clean_json_encoder(&object);
- } else if (res == 2) { //Bonus Malus
- cBonus++;
- add_array_object(&bonus, &object);
- clean_json_encoder(&object);
- }
- //Ajoute coord explosion
- add_integer(&coord, "x", x);
- add_integer(&coord, "y", y - 1 - i);
- add_array_object(&explosion, &coord);
- clean_json_encoder(&coord);
- break;
- }
- //Si un joueur
- if (player_collision_index(g, x, y - 1 - i, &index)) {
- if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
- if (g->player[index]->major == 0) {
- //Baisse la vie
- g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
- //Notification du joueur
- describe_player(g->player[index], ¬if);
- if (!notify_client(g->player[index]->cli, "POST", "attack/affect", ¬if)) {
- adderror("Impossible de notifer le client");
- }
- clean_json_encoder(¬if);
- }
- if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
- }
- //Si une bombe
- if (g->map[x][y - 1 - i] == '1' || g->map[x][y - 1 - i] == '2' || g->map[x][y - 1 - i] == '3') {
- cChain++;
- bomb_chain(g, playerIndex, x, y - 1 - i, &chain, &explosion);
- }
- //Si un mur solide
- if (g->map[x][y - 1 - i] == '-') {
- break;
- }
- //Ajoute coord explosion
- add_integer(&coord, "x", x);
- add_integer(&coord, "y", y - 1 - i);
- add_array_object(&explosion, &coord);
- clean_json_encoder(&coord);
- } else {
- break;
- }
- }
- //Vers le bas
- for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
- //Si on est dans la map
- if (y + 1 + i <= g->height) {
- //Si un mur destructible
- if (g->map[x][y + 1 + i] == '*') {
- g->map[x][y + 1 + i] = '_';
- res = spawn_object(g, x, y + 1 + i, &object);
- if (res == 1) { //Bombe
- cBomb++;
- add_array_object(&bomb, &object);
- clean_json_encoder(&object);
- } else if (res == 2) { //Bonus Malus
- cBonus++;
- add_array_object(&bonus, &object);
- clean_json_encoder(&object);
- }
- //Ajoute coord explosion
- add_integer(&coord, "x", x);
- add_integer(&coord, "y", y + 1 + i);
- add_array_object(&explosion, &coord);
- clean_json_encoder(&coord);
- break;
- }
- //Si un joueur
- if (player_collision_index(g, x, y + 1 + i, &index)) {
- if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
- if (g->player[index]->major == 0) {
- //Baisse la vie
- g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
- //Notification du joueur
- describe_player(g->player[index], ¬if);
- if (!notify_client(g->player[index]->cli, "POST", "attack/affect", ¬if)) {
- adderror("Impossible de notifer le client");
- }
- clean_json_encoder(¬if);
- }
- if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
- }
- //Si une bombe
- if (g->map[x][y + 1 + i] == '1' || g->map[x][y + 1 + i] == '2' || g->map[x][y + 1 + i] == '3') {
- cChain++;
- bomb_chain(g, playerIndex, x, y + 1 + i, &chain, &explosion);
- }
- //Si un mur solide
- if (g->map[x][y + 1 + i] == '-') {
- break;
- }
- //Ajoute coord explosion
- add_integer(&coord, "x", x);
- add_integer(&coord, "y", y + 1 + i);
- add_array_object(&explosion, &coord);
- clean_json_encoder(&coord);
- } else {
- break;
- }
- }
- //Vers la gauche
- for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
- //Si on est dans la map
- if (x - 1 - i >= 0) {
- //Si un mur destructible
- if (g->map[x - 1 - i][y] == '*') {
- g->map[x - 1 - i][y] = '_';
- res = spawn_object(g, x - 1 - i, y, &object);
- if (res == 1) { //Bombe
- cBomb++;
- add_array_object(&bomb, &object);
- clean_json_encoder(&object);
- } else if (res == 2) { //Bonus Malus
- cBonus++;
- add_array_object(&bonus, &object);
- clean_json_encoder(&object);
- }
- //Ajoute coord explosion
- add_integer(&coord, "x", x - 1 - i);
- add_integer(&coord, "y", y);
- add_array_object(&explosion, &coord);
- clean_json_encoder(&coord);
- break;
- }
- //Si un joueur
- if (player_collision_index(g, x - 1 - i, y, &index)) {
- if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
- if (g->player[index]->major == 0) {
- //Baisse la vie
- g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
- //Notification du joueur
- describe_player(g->player[index], ¬if);
- if (!notify_client(g->player[index]->cli, "POST", "attack/affect", ¬if)) {
- adderror("Impossible de notifer le client");
- }
- clean_json_encoder(¬if);
- }
- if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
- }
- //Si une bombe
- if (g->map[x - 1 - i][y] == '1' || g->map[x - 1 - i][y] == '2' || g->map[x - 1 - i][y] == '3') {
- cChain++;
- bomb_chain(g, playerIndex, x - 1 - i, y, &chain, &explosion);
- }
- //Si un mur solide
- if (g->map[x - 1 - i][y] == '-') {
- break;
- }
- //Ajoute coord explosion
- add_integer(&coord, "x", x - 1 - i);
- add_integer(&coord, "y", y);
- add_array_object(&explosion, &coord);
- clean_json_encoder(&coord);
- } else {
- break;
- }
- }
- //Vers la droite
- for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
- //Si on est dans la map
- if (x + 1 + i >= 0) {
- //Si un mur destructible
- if (g->map[x + 1 + i][y] == '*') {
- g->map[x + 1 + i][y] = '_';
- res = spawn_object(g, x + 1 + i, y, &object);
- if (res == 1) { //Bombe
- cBomb++;
- add_array_object(&bomb, &object);
- clean_json_encoder(&object);
- } else if (res == 2) { //Bonus Malus
- cBonus++;
- add_array_object(&bonus, &object);
- clean_json_encoder(&object);
- }
- //Ajoute coord explosion
- add_integer(&coord, "x", x + 1 + i);
- add_integer(&coord, "y", y);
- add_array_object(&explosion, &coord);
- clean_json_encoder(&coord);
- break;
- }
- //Si un joueur
- if (player_collision_index(g, x + 1 + i, y, &index)) {
- if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
- if (g->player[index]->major == 0) {
- //Baisse la vie
- g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
- //Notification du joueur
- describe_player(g->player[index], ¬if);
- if (!notify_client(g->player[index]->cli, "POST", "attack/affect", ¬if)) {
- adderror("Impossible de notifer le client");
- }
- clean_json_encoder(¬if);
- }
- if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
- }
- //Si une bombe
- if (g->map[x + 1 + i][y] == '1' || g->map[x + 1 + i][y] == '2' || g->map[x + 1 + i][y] == '3') {
- cChain++;
- bomb_chain(g, playerIndex, x + 1 + i, y, &chain, &explosion);
- }
- //Si un mur solide
- if (g->map[x + 1 + i][y] == '-') {
- break;
- }
- //Ajoute coord explosion
- add_integer(&coord, "x", x + 1 + i);
- add_integer(&coord, "y", y);
- add_array_object(&explosion, &coord);
- clean_json_encoder(&coord);
- } else {
- break;
- }
- }
- }//Si c'est une mine
- else {
- g->map[x][y] = '_';
- //Calcul dommage
- if (g->player[playerIndex]->major == 0) {
- //Baisse la vie
- g->player[playerIndex]->life = g->player[playerIndex]->life - (g->player[playerIndex]->maxLife * DAMAGEMINE);
- //Notification du joueur
- describe_player(g->player[playerIndex], ¬if);
- if (!notify_client(g->player[playerIndex]->cli, "POST", "attack/affect", ¬if)) {
- adderror("Impossible de notifer le client");
- }
- clean_json_encoder(¬if);
- }
- //Bas de bonus si mine
- add_boolean(json, "bonus", false);
- }
- //Affichage de la map
- free(g->mapContent);
- g->mapContent = unparse_map(g->map, g->width, g->height);
- add_string(json, "map", g->mapContent);
- //Ajout des json
- add_array(json, "bomb", &bomb);
- add_array(json, "bonusMalus", &bonus);
- add_array(json, "chain", &chain);
- add_array(json, "explosion", &explosion);
- //Nettoyage
- if (playerIndex >= 0) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
- pthread_mutex_unlock(&gameMutex[g->index]);
- clean_json_array(&bomb);
- clean_json_array(&bonus);
- clean_json_array(&chain);
- clean_json_array(&explosion);
- return true;
- }
- void bomb_chain(Game* g, int playerIndex, int x, int y, JsonArray* chain, JsonArray* explosion) {
- JsonEncoder json, notif, coord;
- int index;
- Player* p;
- obj_node* objn = NULL;
- //Inie json
- ini_encoder(&json);
- ini_encoder(¬if);
- ini_encoder(&coord);
- //Determine le type de la bombe
- switch (g->map[x][y]) {
- case '1':
- add_string(&json, "type", "classic");
- p = search_player_object(g, OBJ_BCLASSIC, x, y);
- if (p != NULL) {
- p->classicBomb++;
- p->nbBomb--;
- objn = object_search(p->bomb, OBJ_BCLASSIC, x, y);
- object_delete(p->bomb, objn);
- }
- break;
- case '2':
- add_string(&json, "type", "mine");
- p = search_player_object(g, OBJ_BMINE, x, y);
- if (p != NULL) {
- p->mine++;
- p->nbBomb--;
- objn = object_search(p->bomb, OBJ_BMINE, x, y);
- object_delete(p->bomb, objn);
- }
- break;
- case '3':
- add_string(&json, "type", "remote");
- p = search_player_object(g, OBJ_BREMOTE, x, y);
- if (p != NULL) {
- p->remoteBomb++;
- p->nbBomb--;
- objn = object_search(p->bomb, OBJ_BREMOTE, x, y);
- object_delete(p->bomb, objn);
- }
- break;
- default:
- return;
- }
- //Determine la position de la bombe
- char pos[20];
- memset(pos, 0, 20);
- snprintf(pos, 20, "%d,%d", x, y);
- add_string(&json, "pos", pos);
- //Calcul l'explosion non mine
- if (g->map[x][y] != '2') {
- g->map[x][y] = '_';
- //Vers le haut
- for (int i = 0; i < 2; i++) {
- //Si on est dans la map
- if (y - 1 - i >= 0) {
- //Si un mur destructible
- if (g->map[x][y - 1 - i] == '*') {
- g->map[x][y - 1 - i] = '_';
- //Ajoute coord explosion
- add_integer(&coord, "x", x);
- add_integer(&coord, "y", y - 1 - i);
- add_array_object(explosion, &coord);
- clean_json_encoder(&coord);
- break;
- }
- //Si un joueur
- if (player_collision_index(g, x, y - 1 - i, &index)) {
- if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
- if (g->player[index]->major == 0) {
- //Baisse la vie
- g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
- //Notification du joueur
- describe_player(g->player[index], ¬if);
- if (!notify_client(g->player[index]->cli, "POST", "attack/affect", ¬if)) {
- adderror("Impossible de notifer le client");
- }
- clean_json_encoder(¬if);
- }
- if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
- }
- //Si une bombe
- if (g->map[x][y - 1 - i] == '1' || g->map[x][y - 1 - i] == '2' || g->map[x][y - 1 - i] == '3') {
- bomb_chain(g, playerIndex, x, y - 1 - i, chain, explosion);
- }
- //Si un mur solide
- if (g->map[x][y - 1 - i] == '-') {
- break;
- }
- //Ajoute coord explosion
- add_integer(&coord, "x", x);
- add_integer(&coord, "y", y - 1 - i);
- add_array_object(explosion, &coord);
- clean_json_encoder(&coord);
- } else {
- break;
- }
- }
- //Vers le bas
- for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
- //Si on est dans la map
- if (y + 1 + i <= g->height) {
- //Si un mur destructible
- if (g->map[x][y + 1 + i] == '*') {
- g->map[x][y + 1 + i] = '_';
- //Ajoute coord explosion
- add_integer(&coord, "x", x);
- add_integer(&coord, "y", y + 1 + i);
- add_array_object(explosion, &coord);
- clean_json_encoder(&coord);
- break;
- }
- //Si un joueur
- if (player_collision_index(g, x, y + 1 + i, &index)) {
- if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
- if (g->player[index]->major == 0) {
- //Baisse la vie
- g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
- //Notification du joueur
- describe_player(g->player[index], ¬if);
- if (!notify_client(g->player[index]->cli, "POST", "attack/affect", ¬if)) {
- adderror("Impossible de notifer le client");
- }
- clean_json_encoder(¬if);
- }
- if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
- }
- //Si une bombe
- if (g->map[x][y + 1 + i] == '1' || g->map[x][y + 1 + i] == '2' || g->map[x][y + 1 + i] == '3') {
- bomb_chain(g, playerIndex, x, y + 1 + i, chain, explosion);
- }
- //Si un mur solide
- if (g->map[x][y + 1 + i] == '-') {
- break;
- }
- //Ajoute coord explosion
- add_integer(&coord, "x", x);
- add_integer(&coord, "y", y + 1 + i);
- add_array_object(explosion, &coord);
- clean_json_encoder(&coord);
- } else {
- break;
- }
- }
- //Vers la gauche
- for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
- //Si on est dans la map
- if (x - 1 - i >= 0) {
- //Si un mur destructible
- if (g->map[x - 1 - i][y] == '*') {
- g->map[x - 1 - i][y] = '_';
- //Ajoute coord explosion
- add_integer(&coord, "x", x - 1 - i);
- add_integer(&coord, "y", y);
- add_array_object(explosion, &coord);
- clean_json_encoder(&coord);
- break;
- }
- //Si un joueur
- if (player_collision_index(g, x - 1 - i, y, &index)) {
- if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
- if (g->player[index]->major == 0) {
- //Baisse la vie
- g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
- //Notification du joueur
- describe_player(g->player[index], ¬if);
- if (!notify_client(g->player[index]->cli, "POST", "attack/affect", ¬if)) {
- adderror("Impossible de notifer le client");
- }
- clean_json_encoder(¬if);
- }
- if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
- }
- //Si une bombe
- if (g->map[x - 1 - i][y] == '1' || g->map[x - 1 - i][y] == '2' || g->map[x - 1 - i][y] == '3') {
- bomb_chain(g, playerIndex, x - 1 - i, y, chain, explosion);
- }
- //Si un mur solide
- if (g->map[x - 1 - i][y] == '-') {
- break;
- }
- //Ajoute coord explosion
- add_integer(&coord, "x", x - 1 - i);
- add_integer(&coord, "y", y);
- add_array_object(explosion, &coord);
- clean_json_encoder(&coord);
- } else {
- break;
- }
- }
- //Vers la droite
- for (int i = 0; i < 2 + g->player[playerIndex]->firePower; i++) {
- //Si on est dans la map
- if (x + 1 + i >= 0) {
- //Si un mur destructible
- if (g->map[x + 1 + i][y] == '*') {
- g->map[x + 1 + i][y] = '_';
- //Ajoute coord explosion
- add_integer(&coord, "x", x + 1 + i);
- add_integer(&coord, "y", y);
- add_array_object(explosion, &coord);
- clean_json_encoder(&coord);
- break;
- }
- //Si un joueur
- if (player_collision_index(g, x + 1 + i, y, &index)) {
- if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
- if (g->player[index]->major == 0) {
- //Baisse la vie
- g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * (DAMAGEBOMB - (0.1 * i)));
- //Notification du joueur
- describe_player(g->player[index], ¬if);
- if (!notify_client(g->player[index]->cli, "POST", "attack/affect", ¬if)) {
- adderror("Impossible de notifer le client");
- }
- clean_json_encoder(¬if);
- }
- if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
- }
- //Si une bombe
- if (g->map[x + 1 + i][y] == '1' || g->map[x + 1 + i][y] == '2' || g->map[x + 1 + i][y] == '3') {
- bomb_chain(g, playerIndex, x + 1 + i, y, chain, explosion);
- }
- //Si un mur solide
- if (g->map[x + 1 + i][y] == '-') {
- break;
- }
- //Ajoute coord explosion
- add_integer(&coord, "x", x + 1 + i);
- add_integer(&coord, "y", y);
- add_array_object(explosion, &coord);
- clean_json_encoder(&coord);
- } else {
- break;
- }
- }
- }//Si c'est une mine
- else {
- g->map[x][y] = '_';
- //Recup le joueur
- if (player_collision_index(g, x, y, &index)) {
- if (index != playerIndex) pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + index]);
- if (g->player[index]->major == 0) {
- //Baisse la vie
- g->player[index]->life = g->player[index]->life - (g->player[index]->maxLife * DAMAGEMINE);
- //Notification du joueur
- describe_player(g->player[index], ¬if);
- if (!notify_client(g->player[index]->cli, "POST", "attack/affect", ¬if)) {
- adderror("Impossible de notifer le client");
- }
- clean_json_encoder(¬if);
- }
- if (index != playerIndex) pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + index]);
- }
- }
- //Ajoute json dans le tableau
- add_array_object(chain, &json);
- //Nettoyage
- clean_json_encoder(&json);
- }
- int spawn_object(Game* g, int x, int y, JsonEncoder* json) {
- int random, res = 0;
- //Generation random si spawn ou non
- srand(time(NULL));
- random = rand() % 100 + 1;
- if (random > SPAWNRATE) {
- return 0; //Pas de spawn
- }
- //Choisit l'objet
- random = rand() % 11;
- switch (random) {
- case OBJ_BCLASSIC:
- res = 1;
- add_string(json, "type", "classic");
- break;
- case OBJ_BMINE:
- res = 1;
- add_string(json, "type", "mine");
- break;
- case OBJ_BREMOTE:
- res = 1;
- add_string(json, "type", "remote");
- break;
- case OBJ_BOMBUP:
- res = 2;
- add_string(json, "type", "bomb_up");
- break;
- case OBJ_BOMBDOWN:
- res = 2;
- add_string(json, "type", "bomb_down");
- break;
- case OBJ_FIREPOWER:
- res = 2;
- add_string(json, "type", "fire_power");
- break;
- case OBJ_SCOOTER:
- res = 2;
- add_string(json, "type", "scooter");
- break;
- case OBJ_BROKENLEG:
- res = 2;
- add_string(json, "type", "broken_legs");
- break;
- case OBJ_LIFEUP:
- res = 2;
- add_string(json, "type", "life_up");
- break;
- case OBJ_LIFEMAX:
- res = 2;
- add_string(json, "type", "life_max");
- break;
- case OBJ_MAJOR:
- res = 2;
- add_string(json, "type", "major");
- break;
- }
- //Ajoute l'objet dans la partie
- object_add(g->object, random, x, y);
- //Ajoute postion au json
- char pos[20];
- memset(pos, 0, 20);
- snprintf(pos, 20, "%d,%d", x, y);
- add_string(json, "pos", pos);
- //Retourne type d'ajout
- return res;
- }
- void remove_player(Game* g, int playerIndex) {
- pthread_mutex_lock(&gameMutex[g->index]);
- pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
- g->nbPlayer--;
- delete_player(g->player[playerIndex]);
- pthread_mutex_unlock(&gameMutex[g->index]);
- pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + playerIndex]);
- }
- void stop_game(Game* g) {
- pthread_mutex_lock(&gameMutex[g->index]);
- //Indique comme inactive
- g->active = false;
- //Suppr les joueurs
- for (int i = 0; i < MAXPLAYER; i++) {
- //pthread_mutex_lock(&playerMutex[(g->index * MAXPLAYER) + i]);
- if (g->player[i]->ini) {
- delete_player(g->player[i]);
- }
- free(g->player[i]);
- //pthread_mutex_unlock(&playerMutex[(g->index * MAXPLAYER) + i]);
- }
- //Libere la memoire
- object_clean(g->object);
- free(g->object);
- for (int i = 0; i < g->width; i++) {
- free(g->map[i]);
- }
- free(g->map);
- free(g->mapName);
- free(g->mapContent);
- pthread_mutex_unlock(&gameMutex[g->index]);
- //Retire une game
- nbGame--;
- }
- void clean_games() {
- for (int i = 0; i < MAXGAME; i++) {
- if (game[i].active) {
- pthread_mutex_unlock(&gameMutex[i]);
- stop_game(&game[i]);
- }
- }
- }
|