#include #include #include #include #include #include "game.h" #include "game_aux.h" typedef unsigned int uint; /* ********** DUMMY ********** */ bool test_dummy(void) { return EXIT_SUCCESS; } /* ******* game_is_over ******* */ bool test_game_is_over(void) { game g = game_default_solution(); game_update_flags(g); assert(game_is_over(g)); game_set_square(g, 0, 0, (S_LIGHTBULB | F_LIGHTED | F_ERROR)); assert(!game_is_over(g)); game_update_flags(g); game_set_square(g, 0, 1, S_BLANK); assert(!game_is_over(g)); game_delete(g); g = game_default(); game_update_flags(g); assert(!game_is_over(g)); game_delete(g); return EXIT_SUCCESS; } /* ******* game_restart ******* */ bool test_game_restart(void) { game g = game_default(); game g1 = game_default_solution(); game_set_square(g, 1, 5, S_BLACK4); game_set_square(g1, 1, 5, S_BLACK4); game_set_square(g, 3, 2, S_BLACK3); game_set_square(g1, 3, 2, S_BLACK3); game_set_square(g, 0, 1, S_LIGHTBULB); game_set_square(g1, 0, 1, S_LIGHTBULB); game_play_move(g, 2, 0, S_MARK); game_play_move(g1, 2, 0, S_MARK); assert(!game_equal(g, g1)); game_restart(g1); game_restart(g); assert(game_equal(g, g1)); game_delete(g); game_delete(g1); return EXIT_SUCCESS; } /* ********* game_new ********* */ bool test_game_new(void) { square tab[DEFAULT_SIZE * DEFAULT_SIZE]; game g; square list[] = {S_BLANK, S_LIGHTBULB, S_MARK, S_BLACK, S_BLACK0, S_BLACK1, S_BLACK2, S_BLACK3, S_BLACK4, S_BLACKU, F_ERROR}; for (uint i = 0; i < sizeof(list) / sizeof(list[0]); i++) { g = NULL; for (uint j = 0; j < DEFAULT_SIZE * DEFAULT_SIZE; j++) { tab[j] = list[i]; } printf("%d\n", i); g = game_new(tab); assert(g); game_delete(g); } return EXIT_SUCCESS; } /* ******** game_print ******** */ // est ce qu'il faut faire avec un tab invalide ? bool test_game_print(void) { square tab[DEFAULT_SIZE * DEFAULT_SIZE]; square list[] = {S_BLANK, S_LIGHTBULB, S_MARK, S_BLACK0, S_BLACK1, S_BLACK2, S_BLACK3, S_BLACK4, S_BLACKU}; game g; for (uint i = 0; i < sizeof(list) / sizeof(list[0]); i++) { for (uint j = 0; j < DEFAULT_SIZE * DEFAULT_SIZE; j++) { tab[j] = list[i]; } printf("%d\n", i); g = game_new(tab); assert(g); game_print(g); game_delete(g); } return EXIT_SUCCESS; } /* ******* game_get_square ******* */ bool test_game_get_square(void) { game g; square tab[DEFAULT_SIZE * DEFAULT_SIZE]; square list[] = {S_BLANK, S_LIGHTBULB, S_MARK, S_BLACK, S_BLACK0, S_BLACK1, S_BLACK2, S_BLACK3, S_BLACK4, S_BLACKU, F_ERROR}; for (uint i = 0; i < sizeof(list) / sizeof(list[0]); i++) { for (uint j = 0; j < DEFAULT_SIZE * DEFAULT_SIZE; j++) { tab[j] = list[i]; g = game_new(tab); printf( "[%d, %d] %d %d\n", j / (DEFAULT_SIZE), j - (j / (DEFAULT_SIZE)) - (j / (DEFAULT_SIZE) * (DEFAULT_SIZE - 1)), game_get_square(g, j / (DEFAULT_SIZE), j - (j / (DEFAULT_SIZE)) - (j / (DEFAULT_SIZE) * (DEFAULT_SIZE - 1))), tab[j]); assert(game_get_square(g, j / (DEFAULT_SIZE), j - (j / (DEFAULT_SIZE)) - (j / (DEFAULT_SIZE) * (DEFAULT_SIZE - 1))) == tab[j]); game_delete(g); } } return EXIT_SUCCESS; } /* ******* game_default ******* */ bool test_game_default(void) { game g = game_default(); // a verif aps sur assert(g); // clang-format off square tab[49] = { /*X0 X1 X2 X3 X4 X5 X6*/ /*Y 0*/ S_BLANK, S_BLANK, S_BLACK1, S_BLANK, S_BLANK, S_BLANK, S_BLANK, /*Y 1*/ S_BLANK, S_BLANK, S_BLACK2, S_BLANK, S_BLANK, S_BLANK, S_BLANK, /*Y 2*/ S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLACKU, S_BLACK2, /*Y 3*/ S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK, /*Y 4*/ S_BLACK1, S_BLACKU, S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK, /*Y 5*/ S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLACK2, S_BLANK, S_BLANK, /*Y 6*/ S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLACKU, S_BLANK, S_BLANK }; // clang-format on game g1 = game_new(tab); assert(game_equal(g, g1)); game_delete(g); game_delete(g1); return EXIT_SUCCESS; } /* *** game_default_solution *** */ bool test_game_default_solution(void) { game g = game_default_solution(); game g1 = game_default(); assert(g); // solution game_set_square(g1, 0, 0, S_LIGHTBULB); game_set_square(g1, 1, 1, S_LIGHTBULB); game_set_square(g1, 0, 3, S_LIGHTBULB); game_set_square(g1, 1, 6, S_LIGHTBULB); game_set_square(g1, 2, 2, S_LIGHTBULB); game_set_square(g1, 3, 6, S_LIGHTBULB); game_set_square(g1, 4, 4, S_LIGHTBULB); game_set_square(g1, 5, 0, S_LIGHTBULB); game_set_square(g1, 5, 5, S_LIGHTBULB); game_set_square(g1, 6, 1, S_LIGHTBULB); game_update_flags(g1); assert(game_equal(g, g1)); game_delete(g); game_delete(g1); return EXIT_SUCCESS; } /* **** game_update_flags **** */ int checklightbulb(game g, uint i, uint j, bool wall) { square flags = game_get_flags(g, i, j); // square state = game_get_state(g,i,j); // test if the current case is a lightbulb and if it has been well updated // if true we can break the loop because every others cases wont be lighted // by the bulb we are testing if (game_is_lightbulb(g, i, j)) { if (/*test if this lightbulb is well updated*/ flags == S_BLANK || flags == F_ERROR) { // printf("156\n"); return 0; } return -1; } // if no wall(s) before test if the light of the lightbulb has been well // updated if (!wall) { // test if the current case is not lighted if (flags != F_LIGHTED) { // printf("170\n"); return 0; } } else { if (/*test if the current case is lighted*/ flags == F_LIGHTED) { // printf("i:%d j:%d\n",i,j); for (int i2 = i - 1; i2 >= 0; i2--) { flags = game_get_square(g, i2, j); // printf("i2:%d i2state:%d i2flags:%d\n",i2,state,flags); if (flags == (S_LIGHTBULB | F_LIGHTED) || flags == (S_LIGHTBULB | F_LIGHTED | F_ERROR)) { return -1; } if (flags != F_LIGHTED && flags != (F_LIGHTED | S_MARK)) { break; } } for (int i2 = i + 1; i2 < DEFAULT_SIZE; i2++) { flags = game_get_square(g, i2, j); if (flags == (S_LIGHTBULB | F_LIGHTED) || flags == (S_LIGHTBULB | F_LIGHTED | F_ERROR)) { return -1; } if (flags != F_LIGHTED && flags != (F_LIGHTED | S_MARK)) { break; } } for (int j2 = j - 1; j2 >= 0; j2--) { flags = game_get_square(g, i, j2); if (flags == (S_LIGHTBULB | F_LIGHTED) || flags == (S_LIGHTBULB | F_LIGHTED | F_ERROR)) { return -1; } if (flags != F_LIGHTED && flags != (F_LIGHTED | S_MARK)) { break; } } for (int j2 = j + 1; j2 < DEFAULT_SIZE; j2++) { flags = game_get_square(g, i, j2); if (flags == (S_LIGHTBULB | F_LIGHTED) || flags == (S_LIGHTBULB | F_LIGHTED | F_ERROR)) { return -1; } if (flags != F_LIGHTED && flags != (F_LIGHTED | S_MARK)) { break; } } // printf("220\n"); return 0; } } return 1; } bool check_update(game g) { uint size; square choice[4]; uint lb; uint notempty; bool res; bool wall; for (uint i = 0; i < DEFAULT_SIZE; i++) { for (uint j = 0; j < DEFAULT_SIZE; j++) { if (game_is_lightbulb(g, i, j)) { square flags = game_get_flags(g, i, j); if (/*test if this lightbulb is well updated*/ flags == S_BLANK || flags == F_ERROR) { // printf("196\n"); return false; } // loop checking every case before i wall = false; for (int k = i - 1; k > 0; k--) { if (/*test if current case is a wall*/ game_is_black(g, k, j)) { wall = true; } else { int tmp = checklightbulb(g, k, j, wall); if (tmp == -1) { break; } if (!tmp) { return tmp; } } } wall = false; for (int k = i + 1; k < DEFAULT_SIZE; k++) { if (/*test if current case is a wall*/ game_is_black(g, k, j)) { wall = true; } else { int tmp = checklightbulb(g, k, j, wall); if (tmp == -1) { break; } if (!tmp) { return tmp; } } } wall = false; for (int k = j - 1; k > 0; k--) { if (/*test if current case is a wall*/ game_is_black(g, i, k)) { wall = true; } else { int tmp = checklightbulb(g, i, k, wall); if (tmp == -1) { break; } if (!tmp) { return tmp; } } } wall = false; for (int k = j + 1; k < DEFAULT_SIZE; k++) { if (/*test if current case is a wall*/ game_is_black(g, i, k)) { wall = true; } else { int tmp = checklightbulb(g, i, k, wall); if (tmp == -1) { break; } if (!tmp) { return tmp; } } } } else if (/*test if current case is a wall*/ game_is_black(g, i, j)) { if (game_get_black_number(g, i, j) != -1) { // lookup for lightbulb and emptycells size = 0; lb = 0; notempty = 0; res = true; if (i > 0) { choice[size] = game_get_square(g, i - 1, j); size++; } else { notempty++; } if (i < DEFAULT_SIZE - 1) { choice[size] = game_get_square(g, i + 1, j); size++; } else { notempty++; } if (j > 0) { choice[size] = game_get_square(g, i, j - 1); size++; } else { notempty++; } if (j < DEFAULT_SIZE - 1) { choice[size] = game_get_square(g, i, j + 1); size++; } else { notempty++; } for (int l = 0; l < size; l++) { if (choice[l] == (S_LIGHTBULB | F_LIGHTED) || choice[l] == (S_LIGHTBULB | F_LIGHTED | F_ERROR)) { lb++; } else if (choice[l] != S_BLANK) { notempty++; } } if (lb > game_get_black_number(g, i, j)) { res = false; } // look if there is enough empty cell around the wall else if (notempty > abs(game_get_black_number(g, i, j) - 4)) { res = false; } if (game_get_flags(g, i, j) == F_ERROR) { res = !res; } if (!res) { // printf("386\n"); // printf("lb:%d notempty:%d i:%d j:%d state : %d, // flags: // %d\n",lb,notempty,i,j,game_get_state(g,i,j),game_get_flags(g,i,j)); return res; } } } } } return true; } // a > 2 = temps d'exec > 3 min et expo bool brutforce(game g, int a, bool* deldup) { // char c; bool* delDupNext = (bool*)calloc(DEFAULT_SIZE * DEFAULT_SIZE, sizeof(bool)); if (delDupNext == NULL) { fprintf(stderr, "Not enought memory\n"); exit(EXIT_FAILURE); } square list[] = {S_LIGHTBULB, S_MARK, S_BLACK0, S_BLACK1, S_BLACK2, S_BLACK3, S_BLACK4, S_BLACKU, S_BLANK}; for (uint i = 0; i < DEFAULT_SIZE; i++) { for (uint j = 0; j < DEFAULT_SIZE; j++) { // printf("state: %d i:%d j:%d\n",game_get_state(g,i,j),i,j); if (deldup == NULL || !(deldup[i * DEFAULT_SIZE + j])) { if (game_get_state(g, i, j) == S_BLANK) { if (delDupNext != NULL && a > 0) delDupNext[i * DEFAULT_SIZE + j] = true; for (uint k = 0; k < 9; k++) { game_set_square(g, i, j, list[k]); // if (k == 0){ // game_print(g); // scanf("%c",&c); // } if (a > 0) { if (!brutforce(g, a - 1, delDupNext)) { // printf("341\n"); free(delDupNext); return false; } } game_update_flags(g); if (!check_update(g)) { game_print(g); // printf("i:%d j:%d state : %d, flags: // %d\n",i,j,game_get_state(g,i,j),game_get_flags(g,i,j)); free(delDupNext); return false; } } } } } } free(delDupNext); return true; } bool test_game_update_flags(void) { game g = game_default(); assert(g); if (!brutforce(g, 1, NULL)) { game_delete(g); return EXIT_FAILURE; } game_delete(g); return EXIT_SUCCESS; } /* ****** game_play_move ****** */ bool test_game_play_move(void) { game g = game_new_empty(); game g1 = game_new_empty(); game_play_move(g, 0, 0, S_LIGHTBULB); assert(!game_equal(g, g1)); game_set_square(g1, 0, 0, S_LIGHTBULB); assert(!game_equal(g, g1)); game_update_flags(g1); assert(game_equal(g, g1)); game_play_move(g, 3, 0, S_MARK); assert(!game_equal(g, g1)); game_set_square(g1, 3, 0, S_MARK); assert(!game_equal(g, g1)); game_update_flags(g1); assert(game_equal(g, g1)); game_play_move(g, 0, 3, S_BLANK); assert(game_equal(g, g1)); game_set_square(g1, 0, 3, S_BLANK); assert(!game_equal(g, g1)); game_update_flags(g1); assert(game_equal(g, g1)); game_delete(g); game_delete(g1); return EXIT_SUCCESS; } /* ***** game_check_move ***** */ bool test_game_check_move(void) { game g = game_new_empty(); assert(!game_check_move(g, 10, 10, S_BLANK)); assert(!game_check_move(g, 10, 10, S_BLACK0)); assert(!game_check_move(g, 0, 0, S_BLACK0)); assert(!game_check_move(g, 0, 0, S_BLACK1)); assert(!game_check_move(g, 0, 0, S_BLACK2)); assert(!game_check_move(g, 0, 0, S_BLACK3)); assert(!game_check_move(g, 0, 0, S_BLACK4)); assert(!game_check_move(g, 0, 0, S_BLACKU)); assert(!game_check_move(g, 0, 0, F_LIGHTED)); assert(!game_check_move(g, 0, 0, F_ERROR)); for (uint i = 0; i < S_BLACKU - S_BLACK0; i++) { game_set_square(g, 0, 0, S_BLACK0 + i); assert(!game_check_move(g, 0, 0, S_BLANK)); assert(!game_check_move(g, 0, 0, S_MARK)); assert(!game_check_move(g, 0, 0, S_LIGHTBULB)); } assert(game_check_move(g, 1, 0, S_BLANK)); assert(game_check_move(g, 1, 0, S_MARK)); assert(game_check_move(g, 1, 0, S_LIGHTBULB)); game_delete(g); return EXIT_SUCCESS; } /* ********** USAGE ********** */ int usage(int argc, char* argv[]) { fprintf(stderr, "Usage: %s [<...>]\n", argv[0]); exit(EXIT_FAILURE); } /* ********** MAIN ********** */ int main(int argc, char* argv[]) { if (argc == 1) { usage(argc, argv); } fprintf(stderr, "=> Start test \"%s\"\n", argv[1]); bool ok = true; if (strcmp("dummy", argv[1]) == 0) ok = test_dummy(); else if (strcmp("game_print", argv[1]) == 0) ok = test_game_print(); else if (strcmp("game_default", argv[1]) == 0) ok = test_game_default(); else if (strcmp("game_default_solution", argv[1]) == 0) ok = test_game_default_solution(); else if (strcmp("game_new", argv[1]) == 0) ok = test_game_new(); else if (strcmp("game_restart", argv[1]) == 0) ok = test_game_restart(); else if (strcmp("game_get_square", argv[1]) == 0) ok = test_game_get_square(); else if (strcmp("game_is_over", argv[1]) == 0) ok = test_game_is_over(); else if (strcmp("game_update_flags", argv[1]) == 0) ok = test_game_update_flags(); else if (strcmp("game_play_move", argv[1]) == 0) ok = test_game_play_move(); else if (strcmp("game_check_move", argv[1]) == 0) ok = test_game_check_move(); else { fprintf(stderr, "Error: test \"%s\" not found!\n", argv[1]); exit(EXIT_FAILURE); } // print test result if (!ok) { fprintf(stderr, "Test \"%s\" finished: SUCCESS\n", argv[1]); return EXIT_SUCCESS; } else { fprintf(stderr, "Test \"%s\" finished: FAILURE\n", argv[1]); return EXIT_FAILURE; } }