logic.c (7943B)
1 /** 2 * @file logic.c 3 * @author Mateja Marsenic 4 * @date 30 May 2022 5 * @brief This file contains functions used in games logic. 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 11 #include "game.h" 12 #include "logic.h" 13 #include "utils.h" 14 15 Cell *hash = NULL; 16 17 /** 18 * @brief function that delets cell from hash table utilazing uthash.h 19 */ 20 void deleter(Cell *c) { 21 HASH_DEL(hash, c); 22 free(c); 23 } 24 25 /** 26 * @brief function that returns pointer to the cell in hash table at given 27 * position. 28 */ 29 Cell *get(int row, int col) { 30 Cell *c, t; 31 32 memset(&t, 0, sizeof(Cell)); 33 t.cord.row = row; 34 t.cord.col = col; 35 HASH_FIND(hh, hash, &t.cord, sizeof(Cell_cord), c); 36 37 return c; 38 } 39 40 void insert(int row, int col, int val, int mod) { 41 Cell *c; 42 43 c = get(row, col); 44 if (c == NULL) { 45 MEM_CHECK(c = malloc(sizeof(Cell))); 46 c->cord.row = row; 47 c->cord.col = col; 48 c->val = val; 49 HASH_ADD(hh, hash, cord, sizeof(Cell_cord), c); 50 } 51 c->val += mod; 52 } 53 54 extern int width, height; 55 int isExpanding; 56 57 Cell **save_cells; 58 int save_cells_s; 59 int save_cells_sm; 60 61 int pos_y; 62 int pos_x; 63 64 char *evolution_names[] = {"Normal", "CoExsistance", "Predator", "Virus", 65 "Unknown"}; 66 int evolution_cells[] = {2, 3, 3, 3, 3}; 67 int evolution_size = 5; 68 int evolve_index; 69 int toggle_mod = 2; 70 71 static void (*evolve)(void); 72 static void (*addToCells)(int i, int j, int value); 73 74 /** 75 * @brief function that adds its value to neighbouring cells; 76 */ 77 78 void addToCellsNormal(int i, int j, int value) { 79 int mod = 0; 80 switch (value & 3) { 81 case 1: 82 mod = 4; 83 break; 84 case 2: 85 mod = 32; 86 break; 87 } 88 for (int k = i - 1; k <= i + 1; k++) 89 for (int l = j - 1; l <= j + 1; l++) 90 if (k != i || l != j) 91 insert(k, l, 0, mod); 92 } 93 94 /** 95 * @brief simmilar to addToCellsNormal() with exception that it check for 96 * corners in case of wrapping; 97 */ 98 void addToCellsWrap(int i, int j, int value) { 99 int mod = 0; 100 switch (value & 3) { 101 case 1: 102 mod = 4; 103 break; 104 case 2: 105 mod = 32; 106 break; 107 } 108 109 for (int k = i - 1; k <= i + 1; k++) 110 for (int l = j - 1; l <= j + 1; l++) { 111 int a = WCLAMP(k, height); 112 int b = WCLAMP(l, width); 113 if (a != i || b != j) 114 insert(a, b, 0, mod); 115 } 116 } 117 118 void doAdditions(void) { 119 Cell *c; 120 121 Cell *buff[10000]; 122 int size = 0; 123 for (c = hash; c != NULL; c = c->hh.next) 124 buff[size++] = c; 125 126 for (int i = 0; i < size; i++) 127 addToCells(buff[i]->cord.row, buff[i]->cord.col, buff[i]->val); 128 } 129 130 /** 131 * @brief function responsible for calculation for a game mode called "Normal"; 132 */ 133 void evolveNormal(void) { 134 Cell *c, *c_next; 135 136 doAdditions(); 137 for (c = hash; c != NULL; c = c_next) { 138 c_next = c->hh.next; 139 switch (c->val) { 140 case 9: 141 case 12: 142 case 13: 143 c->val = 1; 144 break; 145 default: 146 deleter(c); 147 } 148 } 149 } 150 151 /** 152 * @brief function responsible for calculation for a game mode called "CoExist"; 153 */ 154 void evolveCoExist(void) { 155 Cell *c, *c_next; 156 157 doAdditions(); 158 int s1, s2, mod; 159 for (c = hash; c != NULL; c = c_next) { 160 c_next = c->hh.next; 161 s2 = c->val >> 5; 162 s1 = (c->val & 31) >> 2; 163 mod = c->val & 3; 164 if (mod == 0) { 165 if ((s1 + s2) == 3) { 166 if (c->val >= 64) 167 c->val = 2; 168 else 169 c->val = 1; 170 continue; 171 } 172 } 173 if ((s1 + s2) < 2 || (s1 + s2) > 3) { 174 deleter(c); 175 } 176 c->val = mod; 177 } 178 } 179 180 /** 181 * @brief function responsible for calculation for a game mode called 182 * "Predator"; 183 */ 184 void evolvePredator(void) { 185 Cell *c, *c_next; 186 doAdditions(); 187 int s1, s2, mod; 188 for (c = hash; c != NULL; c = c_next) { 189 c_next = c->hh.next; 190 s2 = c->val >> 5; 191 s1 = (c->val & 31) >> 2; 192 mod = c->val & 3; 193 if ((s1 + s2) < 2 || (s1 + s2) > 3) { 194 deleter(c); 195 continue; 196 } 197 switch (mod) { 198 case 0: 199 if ((s1 + s2) == 3) { 200 if (c->val >= 64) 201 c->val = 2; 202 else 203 c->val = 1; 204 continue; 205 } 206 deleter(c); 207 break; 208 case 1: 209 if (s2 > 0) { 210 deleter(c); 211 continue; 212 } 213 break; 214 } 215 c->val = mod; 216 } 217 } 218 219 /** 220 * @brief function responsible for calculation for a game mode called "Virus"; 221 */ 222 void evolveVirus(void) { 223 Cell *c, *c_next; 224 doAdditions(); 225 int s1, s2, mod; 226 for (c = hash; c != NULL; c = c_next) { 227 c_next = c->hh.next; 228 s2 = c->val >> 5; 229 s1 = (c->val & 31) >> 2; 230 mod = c->val & 3; 231 if ((s1 + s2) < 2 || (s1 + s2) > 3) { 232 deleter(c); 233 continue; 234 } 235 switch (mod) { 236 case 0: 237 if ((s1 + s2) == 3) { 238 if (c->val >= 64) 239 c->val = 2; 240 else 241 c->val = 1; 242 continue; 243 } 244 deleter(c); 245 break; 246 case 1: 247 if (s2 > 0) { 248 c->val = 2; 249 continue; 250 } 251 break; 252 } 253 c->val = mod; 254 } 255 } 256 257 /** 258 * @brief function responsible for calculation for a game mode called "Unknown"; 259 */ 260 void evolveUnknown(void) { // Assumption 3 ones and 3 twos result in 50/50 261 // chanse of 0 becoming one of them: 262 Cell *c, *c_next; 263 doAdditions(); 264 int s1, s2, mod; 265 for (c = hash; c != NULL; c = c_next) { 266 c_next = c->hh.next; 267 s2 = c->val >> 5; 268 s1 = (c->val & 31) >> 2; 269 mod = c->val & 3; 270 switch (mod) { 271 case 0: 272 if (s1 == 3 && s2 == 3) { 273 c->val = rand() % 2 + 1; 274 continue; 275 } 276 if (s1 == 3) { 277 c->val = 1; 278 continue; 279 } 280 if (s2 == 3) { 281 c->val = 2; 282 continue; 283 } 284 deleter(c); 285 break; 286 case 1: 287 if (s1 < 2 || s1 > 3) { 288 deleter(c); 289 continue; 290 } 291 break; 292 case 2: 293 if (s2 < 2 || s2 > 3) { 294 deleter(c); 295 continue; 296 } 297 break; 298 } 299 c->val = mod; 300 } 301 } 302 303 /* Initializing functions */ 304 static void (*evolution_modes[])() = { 305 evolveNormal, evolveCoExist, evolvePredator, evolveVirus, evolveUnknown}; 306 static void (*addition_modes[])(int i, int j, int value) = {addToCellsNormal, 307 addToCellsWrap}; 308 309 /** 310 * @brief parent function that calls evolution; 311 */ 312 void do_evolution(int steps) { 313 while (steps--) { 314 evolve(); 315 } 316 } 317 318 /** 319 * @brief init function for game logic; 320 */ 321 int logic_init(int isWrapping, int index) { 322 save_cells_s = 0; 323 save_cells_sm = 100; 324 MEM_CHECK(save_cells = malloc(save_cells_sm * sizeof(struct Cell *))); 325 326 addToCells = addition_modes[isWrapping]; 327 evolve = evolution_modes[index]; 328 evolve_index = index; 329 toggle_mod = evolution_cells[index]; 330 return 1; 331 } 332 333 /** 334 * @brief memory cleaner for logic.c; 335 */ 336 int logic_free(void) { 337 HASH_CLEAR(hh, hash); 338 addToCells = NULL; 339 evolve = NULL; 340 toggle_mod = -1; 341 free(save_cells); 342 save_cells_s = 0; 343 return 1; 344 } 345 346 /** 347 * @brief function that toggles the value at coords (i,j). E.g from 0->1, 1->2 348 * or 2->0; 349 */ 350 int toggleAt(int i, int j) { 351 Cell *c; 352 353 if (!(c = get(i, j))) { 354 insert(i, j, 1, 0); 355 return 1; 356 } 357 358 int val = c->val = (c->val + 1) % toggle_mod; 359 if (!c->val) 360 deleter(c); 361 return val; 362 } 363 364 /** 365 * @brief function that destroys cell at coords(i,j); 366 */ 367 void deleteAt(int i, int j) { 368 Cell *c; 369 370 if ((c = get(i, j))) 371 deleter(c); 372 } 373 374 /** 375 * @brief function that sets value(val) at coords(i,j); 376 */ 377 void setAt(int i, int j, int val) { 378 Cell *c; 379 380 if ((c = get(i, j)) != NULL) 381 c->val = val; 382 else 383 insert(i, j, val, 0); 384 } 385 386 /** 387 * @brief functiong that returns value of a cell at given coords. 388 */ 389 int getAt(int i, int j) { 390 Cell *c = get(i, j); 391 return ((c) ? c->val : 0); 392 } 393 394 void setPosition(int i, int j) { 395 pos_y = i; 396 pos_x = j; 397 } 398 399 void saveCell(int i, int j) { 400 Cell *c; 401 402 if ((c = get(i, j))) { 403 if (save_cells_s == save_cells_sm) { 404 Cell **t; 405 save_cells_sm *= 2; 406 MEM_CHECK(t = realloc(save_cells, save_cells_sm)); 407 save_cells = t; 408 } 409 410 save_cells[save_cells_s++] = c; 411 } 412 }