diff --git a/include/libmy.h b/include/libmy.h index 4722355..754f7db 100644 --- a/include/libmy.h +++ b/include/libmy.h @@ -6,6 +6,7 @@ */ #include + #ifndef LIBMY_H #define LIBMY_H void my_putchar(char c); diff --git a/include/sokoban.h b/include/sokoban.h index 8efce27..f4ab044 100644 --- a/include/sokoban.h +++ b/include/sokoban.h @@ -7,43 +7,72 @@ #ifndef BSQ_H #define BSQ_H - typedef struct sokoban { - char *buffer; - char **map; - char **map_save; - int lines; - int player_x; - int player_y; - char const *base_path; - int win; - int case_number; - int num_chars_map; - } sokoban_t; - int helper(void); - char *read_map(int reading); - char *open_map(char const *path); - sokoban_t make_map(char const *path, sokoban_t sokoban); - int play(char const *path); - sokoban_t count_lines(sokoban_t sokoban); - int count_columns(sokoban_t sokoban, int position); - sokoban_t check_if_player(sokoban_t sokoban, int y, int x); - sokoban_t find_player(sokoban_t sokoban); - sokoban_t key_check(sokoban_t sokoban, int key); - sokoban_t move_right(sokoban_t sokoban); - sokoban_t move_left(sokoban_t sokoban); - sokoban_t move_up(sokoban_t sokoban); - sokoban_t move_down(sokoban_t sokoban); - void win_check(sokoban_t sokoban); - int count_storage_zone(int y, int x, sokoban_t sokoban); - int count_storage_won(int y, int x, sokoban_t sokoban); - sokoban_t check_zone_reset(sokoban_t sokoban); - sokoban_t reset_zone(int y, int x, sokoban_t sokoban); - void loose_check(sokoban_t sokoban); - void storage_loose_check(int y, int x, sokoban_t sokoban); - void map_check(sokoban_t sokoban); - int count_case_number(int y, int x, sokoban_t sokoban); - int count_player(int y, int x, sokoban_t sokoban); - sokoban_t game_management(sokoban_t sokoban); - int check_tile(int y, int x, sokoban_t sokoban); - int is_goal_cell(int y, int x, sokoban_t sokoban); + +typedef struct sokoban { + char *buffer; + char **map; + char **map_save; + int lines; + int player_x; + int player_y; + char const *base_path; + int win; + int case_number; + int num_chars_map; +} sokoban_t; + +int helper(void); + +char *read_map(int reading); + +char *open_map(char const *path); + +sokoban_t make_map(char const *path, sokoban_t sokoban); + +int play(char const *path); + +sokoban_t count_lines(sokoban_t sokoban); + +int count_columns(sokoban_t sokoban, int position); + +sokoban_t check_if_player(sokoban_t sokoban, int y, int x); + +sokoban_t find_player(sokoban_t sokoban); + +sokoban_t key_check(sokoban_t sokoban, int key); + +sokoban_t move_right(sokoban_t sokoban); + +sokoban_t move_left(sokoban_t sokoban); + +sokoban_t move_up(sokoban_t sokoban); + +sokoban_t move_down(sokoban_t sokoban); + +void win_check(sokoban_t sokoban); + +int count_storage_zone(int y, int x, sokoban_t sokoban); + +int count_storage_won(int y, int x, sokoban_t sokoban); + +sokoban_t check_zone_reset(sokoban_t sokoban); + +sokoban_t reset_zone(int y, int x, sokoban_t sokoban); + +void loose_check(sokoban_t sokoban); + +void storage_loose_check(int y, int x, sokoban_t sokoban); + +void map_check(sokoban_t sokoban); + +int count_case_number(int y, int x, sokoban_t sokoban); + +int count_player(int y, int x, sokoban_t sokoban); + +sokoban_t game_management(sokoban_t sokoban); + +int check_tile(int y, int x, sokoban_t sokoban); + +int is_goal_cell(int y, int x, sokoban_t sokoban); + #endif diff --git a/lib/my_putchar.c b/lib/my_putchar.c index 6803b1e..825f305 100644 --- a/lib/my_putchar.c +++ b/lib/my_putchar.c @@ -8,7 +8,6 @@ #include "../include/libmy.h" #include -void my_putchar(char c) -{ +void my_putchar(char c) { write(1, &c, 1); } diff --git a/lib/my_putchar.o b/lib/my_putchar.o index 0a8815e..3fff90f 100644 Binary files a/lib/my_putchar.o and b/lib/my_putchar.o differ diff --git a/lib/my_putstr.c b/lib/my_putstr.c index a775a71..0d9dddd 100644 --- a/lib/my_putstr.c +++ b/lib/my_putstr.c @@ -7,13 +7,13 @@ #include "../include/libmy.h" -int my_putstr(char const *str) -{ +int my_putstr(char const *str) { int i = 0; while (str[i] != '\0') { my_putchar(str[i]); i++; } + return (0); } diff --git a/lib/my_putstr.o b/lib/my_putstr.o index c706ea4..680174f 100644 Binary files a/lib/my_putstr.o and b/lib/my_putstr.o differ diff --git a/sokoban b/sokoban index aca7830..74045ad 100755 Binary files a/sokoban and b/sokoban differ diff --git a/solution.txt b/solution.txt index f14df7a..60103d9 100644 --- a/solution.txt +++ b/solution.txt @@ -1 +1 @@ -drdrdrdrrruuuuuulllllddrdrdrDulululldRdRdrdRRllululuurdrdrDululldRuuluurrrrrdddddrddlUUUUUUruLLLLLulDDdrdddrdRRlluluurdrDulldruluulldRuuurrrrrdddddrddlUUUUUUruLLLLLulDDdrdrdddRRlluurDldRuulululldRdRluuuurrrrrdddddrddlUUUUUUruLLLLLulDDdrdrdrddRluulululldRdRluuuurrrrrdddddrddlUUUUUUruLLLLLulDD +rrRlllllL diff --git a/src/ai/ai.c b/src/ai/ai.c index 74da426..c3e2191 100644 --- a/src/ai/ai.c +++ b/src/ai/ai.c @@ -1,161 +1,166 @@ -#include -#include #include #include - +#include +#include #include "ai.h" -#include "utils.h" #include "hashtable.h" #include "priority_queue.h" +#include "utils.h" /** * Retrieve solution and return a string containing the squence of moves -*/ -char* save_solution( node_t* solution_node ){ - node_t* n = solution_node; + */ +char *save_solution(node_t *solution_node) { + node_t *n = solution_node; char *solution_string = malloc(sizeof(char) * solution_node->depth+1); solution_string[n->depth] = '\0'; - while (n->parent != NULL) - { + while (n->parent != NULL) { switch (n->move) { - case up: - if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$') - solution_string[n->depth-1] = 'U'; - else - solution_string[n->depth-1] = 'u'; - break; + case up: + if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$') + solution_string[n->depth-1] = 'U'; + else + solution_string[n->depth-1] = 'u'; + break; - case down: - if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$') - solution_string[n->depth-1] = 'D'; - else - solution_string[n->depth-1] = 'd'; - break; + case down: + if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$') + solution_string[n->depth-1] = 'D'; + else + solution_string[n->depth-1] = 'd'; + break; - case left: - if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$') - solution_string[n->depth-1] = 'L'; - else - solution_string[n->depth-1] = 'l'; - break; - - case right: - if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$') - solution_string[n->depth-1] = 'R'; - else - solution_string[n->depth-1] = 'r'; - break; + case left: + if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$') + solution_string[n->depth-1] = 'L'; + else + solution_string[n->depth-1] = 'l'; + break; + case right: + if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$') + solution_string[n->depth-1] = 'R'; + else + solution_string[n->depth-1] = 'r'; + break; } n = n->parent; } + return solution_string; } /** * Copy a src into a dst state -*/ -void copy_state(sokoban_t* init_data, state_t* dst, state_t* src){ + */ +void copy_state(sokoban_t *init_data, state_t *dst, state_t *src) { dst->map = malloc(sizeof(char *) * init_data->lines); - for ( int i = 0; i < init_data->lines; ++i ){ + + for (int i = 0; i < init_data->lines; ++i) { int width = strlen(src->map[i]) + 1; dst->map[i] = malloc(width); memcpy(dst->map[i], src->map[i], width); } + dst->player_x = src->player_x; dst->player_y = src->player_y; } /** * Create the initial node -*/ -node_t* create_init_node( sokoban_t* init_data ){ - node_t * new_n = (node_t *) malloc(sizeof(node_t)); + */ +node_t *create_init_node(sokoban_t *init_data) { + node_t *new_n = (node_t *) malloc(sizeof(node_t)); + new_n->parent = NULL; new_n->priority = 0; new_n->depth = 0; new_n->num_childs = 0; new_n->move = -1; new_n->state.map = malloc(sizeof(char *) * init_data->lines); - for (int i = 0; i < init_data->lines; ++i) - { + + for (int i = 0; i < init_data->lines; ++i) { int width = strlen(init_data->map[i]) + 1; new_n->state.map[i] = malloc(width); memcpy(new_n->state.map[i], init_data->map[i], width); } new_n->state.player_x = init_data->player_x; - new_n->state.player_y = init_data->player_y; + return new_n; } /** * Create the a node from a parent node -*/ -node_t* create_node( sokoban_t* init_data, node_t* parent ){ - node_t * new_n = (node_t *) malloc(sizeof(node_t)); + */ +node_t *create_node(sokoban_t *init_data, node_t *parent) { + node_t *new_n = (node_t *) malloc(sizeof(node_t)); new_n->parent = parent; new_n->depth = parent->depth + 1; copy_state(init_data, &(new_n->state), &(parent->state)); return new_n; - } /** * Apply an action to node n, create a new node resulting from * executing the action, and return if the player moved -*/ -bool applyAction(sokoban_t* init_data, node_t* n, node_t** new_node, move_t action ){ + */ +bool applyAction(sokoban_t *init_data, node_t *n, node_t **new_node, \ + move_t action) { bool player_moved = false; - *new_node = create_node( init_data, n ); + *new_node = create_node(init_data, n); (*new_node)->move = action; (*new_node)->priority = -(*new_node)->depth; - player_moved = execute_move_t( init_data, &((*new_node)->state), action ); + player_moved = execute_move_t(init_data, &((*new_node)->state), action); return player_moved; - } /** * Book keeping variable and function to free memory once the solver finishes -*/ -node_t** expanded_nodes_table; -unsigned expanded_nodes_table_size = 10000000; //10M -void update_explore_table(node_t* n, unsigned expanded_nodes ){ - if( expanded_nodes > expanded_nodes_table_size - 1){ - expanded_nodes_table_size *= 2; - expanded_nodes_table = realloc( expanded_nodes_table, sizeof(node_t*) * expanded_nodes_table_size ); - + */ +node_t **expanded_nodes_table; + +// 10M +unsigned expanded_nodes_table_size = 10000000; + +void update_explore_table(node_t *n, unsigned expanded_nodes) { + if (expanded_nodes > expanded_nodes_table_size - 1) { + expanded_nodes_table_size *= 2; + expanded_nodes_table = realloc(expanded_nodes_table, \ + sizeof(node_t*) * expanded_nodes_table_size); } expanded_nodes_table[ expanded_nodes ] = n; - } -void free_memory(unsigned expanded_nodes ){ - for( unsigned i = 0; i < expanded_nodes; i++){ +void free_memory(unsigned expanded_nodes, int lines) { + for (unsigned i = 0; i < expanded_nodes; i++) { + for (int j = 0; j < lines; j++) { + free(expanded_nodes_table[i]->state.map[j]); + } + free(expanded_nodes_table[i]->state.map); free(expanded_nodes_table[i]); } + free(expanded_nodes_table); } /** * Given a 2D map, returns a 1D map -*/ -void flatten_map( sokoban_t* init_data, char **dst_map, char **src_map){ - + */ +void flatten_map(sokoban_t *init_data, char **dst_map, char **src_map) { int current_i = 0; - for (int i = 0; i < init_data->lines; ++i) - { + for (int i = 0; i < init_data->lines; ++i) { int width = strlen(src_map[i]); - for ( int j = 0; j < width; j++ ){ + for (int j = 0; j < width; j++) { (*dst_map)[current_i] = src_map[i][j]; current_i++; } @@ -165,13 +170,12 @@ void flatten_map( sokoban_t* init_data, char **dst_map, char **src_map){ /** * Find a solution by exploring all possible paths */ -void find_solution(sokoban_t* init_data, bool show_solution) -{ +void find_solution(sokoban_t *init_data, bool show_solution) { // Keep track of solving time clock_t start = clock(); // Solution String containing the sequence of moves - char* solution = NULL; + char *solution = NULL; HashTable hashTable; struct heap pq; @@ -185,32 +189,27 @@ void find_solution(sokoban_t* init_data, bool show_solution) // Choose initial capacity of PRIME NUMBER // Specify the size of the keys and values you want to store once // The Hash Table only accept a 1D key and value. - ht_setup( &hashTable, sizeof(int8_t) * init_data->num_chars_map, sizeof(int8_t) * init_data->num_chars_map, 16769023); - - + ht_setup(&hashTable, sizeof(int8_t) * init_data->num_chars_map, sizeof(int8_t) * init_data->num_chars_map, 16769023); // Data structure to create a 1D representation of the map // Needed to interact with the hash table - char* flat_map = calloc( init_data->num_chars_map, sizeof(char)); + char *flat_map = calloc(init_data->num_chars_map, sizeof(char)); // Initialize heap heap_init(&pq); // Initialize expanded nodes table. // This table will be used to free your memory once a solution is found - expanded_nodes_table = (node_t**) malloc( sizeof(node_t*) * expanded_nodes_table_size ); + expanded_nodes_table = (node_t **) malloc(sizeof(node_t *) * expanded_nodes_table_size); // Add the initial node - node_t* n = create_init_node( init_data ); + node_t *n = create_init_node(init_data); // Use the max heap API provided in priority_queue.h heap_push(&pq,n); - /** - * FILL IN THE GRAPH ALGORITHM - * */ - + // Implementation of Algorithm 1 while (pq.count > 0) { n = heap_delete(&pq); update_explore_table(n, expanded_nodes); @@ -226,6 +225,9 @@ void find_solution(sokoban_t* init_data, bool show_solution) bool player_moved = applyAction(init_data, n, &new, action); generated_nodes += 1; if (!player_moved || simple_corner_deadlock(init_data, &(new->state))) { + for (int i = 0; i < init_data->lines; i++) { + free(new->state.map[i]); + } free(new->state.map); free(new); continue; @@ -235,6 +237,9 @@ void find_solution(sokoban_t* init_data, bool show_solution) if (ht_lookup(&hashTable, flat_map) != NULL) { duplicated_nodes += 1; + for (int i = 0; i < init_data->lines; i++) { + free(new->state.map[i]); + } free(new->state.map); free(new); continue; @@ -243,15 +248,15 @@ void find_solution(sokoban_t* init_data, bool show_solution) ht_insert(&hashTable, flat_map, &flat_map); heap_push(&pq, new); } - } - - //---------------------------- + } // Free Memory of HashTable, Explored and flatmap ht_clear(&hashTable); ht_destroy(&hashTable); - free_memory(expanded_nodes); + free_memory(expanded_nodes, init_data->lines); free(flat_map); + + // Free initial data for (int i = 0; i < init_data->lines; i++) { free((init_data->map)[i]); free((init_data->map_save)[i]); @@ -259,27 +264,38 @@ void find_solution(sokoban_t* init_data, bool show_solution) free(init_data->map); free(init_data->map_save); free(init_data->buffer); - emptyPQ(&pq); - // free(pq.heaparr); - // printf("%d\n", pq.count); - //---------------------------- + // Free priority queue + for (int i = pq.count; i > 0; i--) { + for (int j = 0; j < init_data->lines; j++) { + if (pq.heaparr[i]->state.map[j]) { + free(pq.heaparr[i]->state.map[j]); + } + } + if (pq.heaparr[i]->state.map) { + free(pq.heaparr[i]->state.map); + } + if (pq.heaparr[i]) { + free(pq.heaparr[i]); + } + } + free(pq.heaparr); // Stop clock clock_t end = clock(); double cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; // Show solution - if( show_solution && solution != NULL ) play_solution( *init_data, solution); + if (show_solution && solution != NULL) play_solution(*init_data, solution); endwin(); - if( solution != NULL ){ + if (solution != NULL) { printf("\nSOLUTION: \n"); - printf( "%s\n\n", solution); + printf("%s\n\n", solution); + FILE *fptr = fopen("solution.txt", "w"); - if (fptr == NULL) - { + if (fptr == NULL) { printf("Could not open file"); return ; } @@ -289,34 +305,25 @@ void find_solution(sokoban_t* init_data, bool show_solution) free(solution); } - printf("STATS: \n"); - printf("\tExpanded nodes: %'d\n\tGenerated nodes: %'d\n\tDuplicated nodes: %'d\n", expanded_nodes, generated_nodes, duplicated_nodes); + printf("\tExpanded nodes: %'d\n\tGenerated nodes: %'d\n\t" \ + "Duplicated nodes: %'d\n", expanded_nodes, generated_nodes, \ + duplicated_nodes); printf("\tSolution Length: %d\n", solution_size); - printf("\tExpanded/seconds: %d\n", (int)(expanded_nodes/cpu_time_used) ); - printf("\tTime (seconds): %f\n", cpu_time_used ); - + printf("\tExpanded/seconds: %d\n", (int)(expanded_nodes/cpu_time_used)); + printf("\tTime (seconds): %f\n", cpu_time_used); } -void solve(char const *path, bool show_solution) -{ - /** - * Load Map - */ +void solve(char const *path, bool show_solution) { + // Load Map sokoban_t sokoban = make_map(path, sokoban); + sokoban.base_path = path; - /** - * Count number of boxes and Storage locations - */ + // Count number of boxes and Storage locations map_check(sokoban); - /** - * Locate player x,y position - */ + // Locate player x,y position sokoban = find_player(sokoban); - sokoban.base_path = path; - find_solution(&sokoban, show_solution); - } diff --git a/src/ai/ai.h b/src/ai/ai.h index 23f12ad..e87b37f 100644 --- a/src/ai/ai.h +++ b/src/ai/ai.h @@ -3,6 +3,7 @@ #include #include + #include "node.h" #include "priority_queue.h" diff --git a/src/ai/ai.o b/src/ai/ai.o index 40028f7..fda4a3f 100644 Binary files a/src/ai/ai.o and b/src/ai/ai.o differ diff --git a/src/ai/hashtable.c b/src/ai/hashtable.c index 2675330..40addab 100644 --- a/src/ai/hashtable.c +++ b/src/ai/hashtable.c @@ -3,22 +3,20 @@ */ #include +#include #include #include - -#include - - #include "hashtable.h" -int ht_setup(HashTable* table, - size_t key_size, - size_t value_size, - size_t capacity) { +int ht_setup(HashTable* table, size_t key_size, size_t value_size, \ + size_t capacity) { + assert(table != NULL); - - if (table == NULL) return HT_ERROR; + + if (table == NULL) { + return HT_ERROR; + } if (capacity < HT_MINIMUM_CAPACITY) { capacity = HT_MINIMUM_CAPACITY; @@ -38,14 +36,19 @@ int ht_setup(HashTable* table, } int ht_copy(HashTable* first, HashTable* second) { - size_t chain; - HTNode* node; - assert(first != NULL); assert(ht_is_initialized(second)); - if (first == NULL) return HT_ERROR; - if (!ht_is_initialized(second)) return HT_ERROR; + size_t chain; + HTNode* node; + + if (first == NULL) { + return HT_ERROR; + } + + if (!ht_is_initialized(second)) { + return HT_ERROR; + } if (_ht_allocate(first, second->capacity) == HT_ERROR) { return HT_ERROR; @@ -59,7 +62,9 @@ int ht_copy(HashTable* first, HashTable* second) { for (chain = 0; chain < second->capacity; ++chain) { for (node = second->nodes[chain]; node; node = node->next) { - if (_ht_push_front(first, chain, node->key, node->value) == HT_ERROR) { + if (_ht_push_front(first, chain, node->key, node->value) == \ + HT_ERROR) { + return HT_ERROR; } } @@ -72,8 +77,13 @@ int ht_move(HashTable* first, HashTable* second) { assert(first != NULL); assert(ht_is_initialized(second)); - if (first == NULL) return HT_ERROR; - if (!ht_is_initialized(second)) return HT_ERROR; + if (first == NULL) { + return HT_ERROR; + } + + if (!ht_is_initialized(second)) { + return HT_ERROR; + } *first = *second; second->nodes = NULL; @@ -85,8 +95,13 @@ int ht_swap(HashTable* first, HashTable* second) { assert(ht_is_initialized(first)); assert(ht_is_initialized(second)); - if (!ht_is_initialized(first)) return HT_ERROR; - if (!ht_is_initialized(second)) return HT_ERROR; + if (!ht_is_initialized(first)) { + return HT_ERROR; + } + + if (!ht_is_initialized(second)) { + return HT_ERROR; + } _ht_int_swap(&first->key_size, &second->key_size); _ht_int_swap(&first->value_size, &second->value_size); @@ -104,7 +119,9 @@ int ht_destroy(HashTable* table) { size_t chain; assert(ht_is_initialized(table)); - if (!ht_is_initialized(table)) return HT_ERROR; + if (!ht_is_initialized(table)) { + return HT_ERROR; + } for (chain = 0; chain < table->capacity; ++chain) { node = table->nodes[chain]; @@ -127,8 +144,13 @@ int ht_insert(HashTable* table, void* key, void* value) { assert(ht_is_initialized(table)); assert(key != NULL); - if (!ht_is_initialized(table)) return HT_ERROR; - if (key == NULL) return HT_ERROR; + if (!ht_is_initialized(table)) { + return HT_ERROR; + } + + if (key == NULL) { + return HT_ERROR; + } if (_ht_should_grow(table)) { _ht_adjust_capacity(table); @@ -158,8 +180,13 @@ int ht_contains(HashTable* table, void* key) { assert(ht_is_initialized(table)); assert(key != NULL); - if (!ht_is_initialized(table)) return HT_ERROR; - if (key == NULL) return HT_ERROR; + if (!ht_is_initialized(table)) { + return HT_ERROR; + } + + if (key == NULL) { + return HT_ERROR; + } index = _ht_hash(table, key); for (node = table->nodes[index]; node; node = node->next) { @@ -178,8 +205,13 @@ void* ht_lookup(HashTable* table, void* key) { assert(table != NULL); assert(key != NULL); - if (table == NULL) return NULL; - if (key == NULL) return NULL; + if (table == NULL) { + return NULL; + } + + if (key == NULL) { + return NULL; + } index = _ht_hash(table, key); for (node = table->nodes[index]; node; node = node->next) { @@ -198,8 +230,13 @@ const void* ht_const_lookup(const HashTable* table, void* key) { assert(table != NULL); assert(key != NULL); - if (table == NULL) return NULL; - if (key == NULL) return NULL; + if (table == NULL) { + return NULL; + } + + if (key == NULL) { + return NULL; + } index = _ht_hash(table, key); for (node = table->nodes[index]; node; node = node->next) { @@ -219,8 +256,13 @@ int ht_erase(HashTable* table, void* key) { assert(table != NULL); assert(key != NULL); - if (table == NULL) return HT_ERROR; - if (key == NULL) return HT_ERROR; + if (table == NULL) { + return HT_ERROR; + } + + if (key == NULL) { + return HT_ERROR; + } index = _ht_hash(table, key); node = table->nodes[index]; @@ -241,7 +283,7 @@ int ht_erase(HashTable* table, void* key) { return HT_ERROR; } } - + return HT_SUCCESS; } } @@ -253,8 +295,13 @@ int ht_clear(HashTable* table) { assert(table != NULL); assert(table->nodes != NULL); - if (table == NULL) return HT_ERROR; - if (table->nodes == NULL) return HT_ERROR; + if (table == NULL) { + return HT_ERROR; + } + + if (table->nodes == NULL) { + return HT_ERROR; + } ht_destroy(table); _ht_allocate(table, HT_MINIMUM_CAPACITY); @@ -265,7 +312,11 @@ int ht_clear(HashTable* table) { int ht_is_empty(HashTable* table) { assert(table != NULL); - if (table == NULL) return HT_ERROR; + + if (table == NULL) { + return HT_ERROR; + } + return table->size == 0; } @@ -278,8 +329,8 @@ int ht_reserve(HashTable* table, size_t minimum_capacity) { if (!ht_is_initialized(table)) return HT_ERROR; /* - * We expect the "minimum capacity" to be in elements, not in array indices. - * This encapsulates the design. + * We expect the "minimum capacity" to be in elements, + * not in array indices. This encapsulates the design. */ if (minimum_capacity > table->threshold) { return _ht_resize(table, minimum_capacity / HT_LOAD_FACTOR); @@ -354,9 +405,11 @@ _ht_create_node(HashTable* table, void* key, void* value, HTNode* next) { if ((node = malloc(sizeof *node)) == NULL) { return NULL; } + if ((node->key = malloc(table->key_size)) == NULL) { return NULL; } + if ((node->value = malloc(table->value_size)) == NULL) { return NULL; } @@ -369,7 +422,8 @@ _ht_create_node(HashTable* table, void* key, void* value, HTNode* next) { } int _ht_push_front(HashTable* table, size_t index, void* key, void* value) { - table->nodes[index] = _ht_create_node(table, key, value, table->nodes[index]); + table->nodes[index] = \ + _ht_create_node(table, key, value, table->nodes[index]); return table->nodes[index] == NULL ? HT_ERROR : HT_SUCCESS; } @@ -440,4 +494,4 @@ void _ht_rehash(HashTable* table, HTNode** old, size_t old_capacity) { node = next; } } -} \ No newline at end of file +} diff --git a/src/ai/hashtable.h b/src/ai/hashtable.h index 06c0f68..9e77c51 100644 --- a/src/ai/hashtable.h +++ b/src/ai/hashtable.h @@ -13,23 +13,19 @@ #define HT_MINIMUM_CAPACITY 8 #define HT_LOAD_FACTOR 5 #define HT_MINIMUM_THRESHOLD (HT_MINIMUM_CAPACITY) * (HT_LOAD_FACTOR) - #define HT_GROWTH_FACTOR 2 #define HT_SHRINK_THRESHOLD (1 / 4) - #define HT_ERROR -1 #define HT_SUCCESS 0 - #define HT_UPDATED 1 #define HT_INSERTED 0 - #define HT_NOT_FOUND 0 #define HT_FOUND 01 - #define HT_INITIALIZER {0, 0, 0, 0, 0, NULL, NULL, NULL}; -typedef int (*comparison_t)(void*, void*, size_t); -typedef size_t (*hash_t)(void*, size_t); +typedef int (*comparison_t)(void *, void *, size_t); + +typedef size_t (*hash_t)(void *, size_t); /****************** STRUCTURES ******************/ @@ -58,13 +54,13 @@ typedef struct HashTable { /****************** INTERFACE ******************/ /* Setup */ -int ht_setup(HashTable* table, - size_t key_size, - size_t value_size, - size_t capacity); +int ht_setup(HashTable* table, size_t key_size, size_t value_size, \ + size_t capacity); int ht_copy(HashTable* first, HashTable* second); + int ht_move(HashTable* first, HashTable* second); + int ht_swap(HashTable* first, HashTable* second); /* Destructor */ @@ -73,16 +69,20 @@ int ht_destroy(HashTable* table); int ht_insert(HashTable* table, void* key, void* value); int ht_contains(HashTable* table, void* key); -void* ht_lookup(HashTable* table, void* key); -const void* ht_const_lookup(const HashTable* table, void* key); + +void *ht_lookup(HashTable* table, void* key); + +const void *ht_const_lookup(const HashTable* table, void* key); #define HT_LOOKUP_AS(type, table_pointer, key_pointer) \ (*(type*)ht_lookup((table_pointer), (key_pointer))) int ht_erase(HashTable* table, void* key); + int ht_clear(HashTable* table); int ht_is_empty(HashTable* table); + bool ht_is_initialized(HashTable* table); int ht_reserve(HashTable* table, size_t minimum_capacity); @@ -90,24 +90,34 @@ int ht_reserve(HashTable* table, size_t minimum_capacity); /****************** PRIVATE ******************/ void _ht_int_swap(size_t* first, size_t* second); + void _ht_pointer_swap(void** first, void** second); size_t _ht_default_hash(void* key, size_t key_size); + int _ht_default_compare(void* first_key, void* second_key, size_t key_size); size_t _ht_hash(const HashTable* table, void* key); + bool _ht_equal(const HashTable* table, void* first_key, void* second_key); bool _ht_should_grow(HashTable* table); + bool _ht_should_shrink(HashTable* table); -HTNode* _ht_create_node(HashTable* table, void* key, void* value, HTNode* next); +HTNode *_ht_create_node(HashTable* table, void* key, void* value, \ + HTNode* next); + int _ht_push_front(HashTable* table, size_t index, void* key, void* value); + void _ht_destroy_node(HTNode* node); int _ht_adjust_capacity(HashTable* table); + int _ht_allocate(HashTable* table, size_t capacity); + int _ht_resize(HashTable* table, size_t new_capacity); + void _ht_rehash(HashTable* table, HTNode** old, size_t old_capacity); -#endif /* HASHTABLE_H */ \ No newline at end of file +#endif diff --git a/src/ai/hashtable.o b/src/ai/hashtable.o index ed45f88..f856644 100644 Binary files a/src/ai/hashtable.o and b/src/ai/hashtable.o differ diff --git a/src/ai/node.h b/src/ai/node.h index 0223530..ae81f92 100644 --- a/src/ai/node.h +++ b/src/ai/node.h @@ -3,21 +3,16 @@ #include "utils.h" - - /** * Data structure containing the node information */ -struct node_s{ +typedef struct node_s { int priority; int depth; int num_childs; move_t move; state_t state; struct node_s* parent; -}; - -typedef struct node_s node_t; - +} node_t; #endif diff --git a/src/ai/priority_queue.c b/src/ai/priority_queue.c index a71c428..3d52625 100644 --- a/src/ai/priority_queue.c +++ b/src/ai/priority_queue.c @@ -2,109 +2,115 @@ int *heap, size, count; -void heap_init(struct heap* h) -{ +void heap_init(struct heap *h) { h->count = 0; h->size = initial_size; h->heaparr = (node_t **) malloc(sizeof(node_t*) * initial_size); - for(int i = 0; i < initial_size; i++) - h->heaparr[i]=NULL; + + for (int i = 0; i < initial_size; i++) { + h->heaparr[i] = NULL; + } - if(!h->heaparr) { + if (!h->heaparr) { printf("Error allocatinga memory...\n"); exit(-1); } - } -void max_heapify(node_t** data, int loc, int count) { +void max_heapify(node_t **data, int loc, int count) { int left, right, largest; - node_t* temp; - left = 2*(loc) + 1; + node_t *temp; + left = 2 * (loc) + 1; right = left + 1; largest = loc; - if (left <= count && data[left]->priority > data[largest]->priority) { largest = left; - } + } + if (right <= count && data[right]->priority > data[largest]->priority) { largest = right; - } + } - if(largest != loc) { + if (largest != loc) { temp = data[loc]; data[loc] = data[largest]; data[largest] = temp; max_heapify(data, largest, count); } - } -void heap_push(struct heap* h, node_t* value) -{ +void heap_push(struct heap *h, node_t *value) { int index, parent; // Resize the heap if it is too small to hold all the data - if (h->count == h->size) - { + if (h->count == h->size) { h->size += 1; h->heaparr = realloc(h->heaparr, sizeof(node_t) * h->size); - if (!h->heaparr) exit(-1); // Exit if the memory allocation fails + + // Exit if the memory allocation fails + if (!h->heaparr) { + exit(-1); + } } - - index = h->count++; // First insert at last of array + + // First insert at last of array + index = h->count++; // Find out where to put the element and put it - for(;index; index = parent) - { + for (; index; index = parent) { parent = (index - 1) / 2; - if (h->heaparr[parent]->priority >= value->priority) break; + + if (h->heaparr[parent]->priority >= value->priority) { + break; + } + h->heaparr[index] = h->heaparr[parent]; } + h->heaparr[index] = value; } -void heap_display(struct heap* h, sokoban_t* init_data) { - int i; - for(i=0; icount; ++i) { - node_t* n = h->heaparr[i]; +void heap_display(struct heap *h, sokoban_t *init_data) { + for (int i = 0; i < h->count; ++i) { + node_t *n = h->heaparr[i]; - printf("priority = %d", n->priority); - printf("\n"); - for (int i = 0; i < init_data->lines; i++) - mvprintw(i, 0, n->state.map[i]); + printf("priority = %d\n", n->priority); + + for (int j = 0; i < init_data->lines; j++) { + mvprintw(i, 0, n->state.map[j]); + } + move(n->state.player_y, n->state.player_x); } } -node_t* heap_delete(struct heap* h) -{ - node_t* removed; - node_t* temp = h->heaparr[--h->count]; - +node_t *heap_delete(struct heap *h) { + node_t *removed; + node_t *temp = h->heaparr[--h->count]; - if ((h->count <= (h->size + 2)) && (h->size > initial_size)) - { + if ((h->count <= (h->size + 2)) && (h->size > initial_size)) { h->size -= 1; h->heaparr = realloc(h->heaparr, sizeof(node_t) * h->size); - if (!h->heaparr) exit(-1); // Exit if the memory allocation fails + + // Exit if the memory allocation fails + if (!h->heaparr) exit(-1); } + removed = h->heaparr[0]; h->heaparr[0] = temp; - if(temp == removed) h->heaparr[0] = NULL; - max_heapify(h->heaparr, 0, h->count); + if (temp == removed) { + h->heaparr[0] = NULL; + } + + max_heapify(h->heaparr, 0, h->count); return removed; } -void emptyPQ(struct heap* pq) { +void emptyPQ(struct heap *pq) { while(pq->count != 0) { - node_t* n = heap_delete(pq); - for (int i = size; i >= 0; i--) { - free(n->state.map[i]); - } - free(n->state.map); + node_t *n = heap_delete(pq); free(n); } } diff --git a/src/ai/priority_queue.h b/src/ai/priority_queue.h index f8ca1b4..c11778d 100644 --- a/src/ai/priority_queue.h +++ b/src/ai/priority_queue.h @@ -2,20 +2,19 @@ #define __PQ__ /** - * NIR: Adapted from https://gist.github.com/aatishnn/8265656#file-binarymaxheap-c + * Adapted from https://gist.github.com/aatishnn/8265656#file-binarymaxheap-c */ #include #include #include + #include "node.h" #include "../../include/sokoban.h" - /** * size is the allocated size, count is the number of elements in the queue */ - struct heap { int size; int count; @@ -24,16 +23,16 @@ struct heap { #define initial_size 4 -void heap_init(struct heap* h); +void heap_init(struct heap *h); -void max_heapify(node_t** data, int loc, int count); +void max_heapify(node_t **data, int loc, int count); -void heap_push(struct heap* h, node_t* value); +void heap_push(struct heap *h, node_t *value); void heap_display(struct heap *h, sokoban_t *init_data); -node_t* heap_delete(struct heap* h); +node_t* heap_delete(struct heap *h); -void emptyPQ(struct heap* pq); +void emptyPQ(struct heap *pq); #endif diff --git a/src/ai/priority_queue.o b/src/ai/priority_queue.o index 0302ed6..fd3f269 100644 Binary files a/src/ai/priority_queue.o and b/src/ai/priority_queue.o differ diff --git a/src/ai/utils.c b/src/ai/utils.c index 81b072f..af54f94 100644 --- a/src/ai/utils.c +++ b/src/ai/utils.c @@ -1,256 +1,316 @@ #include +#include + #include "utils.h" +/********* +* MACROS * +*********/ +#define TERMINAL_TYPE (strcmp(getenv("TERM"), "xterm") == 0 ? "rxvt" : \ + getenv("TERM")) /************************************** * Box movement given a state state * ***************************************/ -bool is_goal_loc(int y, int x, sokoban_t* init_data) -{ - return (init_data->map_save[y][x] == '.') || (init_data->map_save[y][x] == '+') || (init_data->map_save[y][x] == '*'); +bool is_goal_loc(int y, int x, sokoban_t *init_data) { + return (init_data->map_save[y][x] == '.') || \ + (init_data->map_save[y][x] == '+') || \ + (init_data->map_save[y][x] == '*'); } +bool push_box_left(sokoban_t *init_data, state_t *state) { + if (state->map[state->player_y][state->player_x-2] == '$' || \ + state->map[state->player_y][state->player_x-2] == '*') { -bool push_box_left(sokoban_t* init_data,state_t* state) -{ - if (state->map[state->player_y][state->player_x-2] == '$' || state->map[state->player_y][state->player_x-2] == '*') { return false; } else if (state->map[state->player_y][state->player_x-2] == '#') { return false; } else { state->map[state->player_y][state->player_x-1] = '@'; - if(state->map[state->player_y][state->player_x-2] == '.') + + if (state->map[state->player_y][state->player_x-2] == '.') { state->map[state->player_y][state->player_x-2] = '*'; - else + } else { state->map[state->player_y][state->player_x-2] = '$'; - + } + state->map[state->player_y][state->player_x] = ' '; - if (is_goal_loc( state->player_y, state->player_x, init_data) && state->map[state->player_y][state->player_x] == ' ') { + + if (is_goal_loc(state->player_y, state->player_x, init_data) && \ + state->map[state->player_y][state->player_x] == ' ') { + state->map[state->player_y][state->player_x] = '.'; } + state->player_x--; } + return true; } -bool push_box_right(sokoban_t* init_data,state_t* state) -{ - if (state->map[state->player_y][state->player_x+2] == '$' || state->map[state->player_y][state->player_x+2] == '*') { +bool push_box_right(sokoban_t *init_data, state_t *state) { + if (state->map[state->player_y][state->player_x+2] == '$' || \ + state->map[state->player_y][state->player_x+2] == '*') { + return false; } else if (state->map[state->player_y][state->player_x+2] == '#') { return false; } else { state->map[state->player_y][state->player_x+1] = '@'; - if(state->map[state->player_y][state->player_x+2] == '.') + + if (state->map[state->player_y][state->player_x+2] == '.') { state->map[state->player_y][state->player_x+2] = '*'; - else + } else { state->map[state->player_y][state->player_x+2] = '$'; + } + state->map[state->player_y][state->player_x] = ' '; - if (is_goal_loc( state->player_y, state->player_x, init_data) && state->map[state->player_y][state->player_x] == ' ') { - state->map[state->player_y][state->player_x] = '.'; + + if (is_goal_loc(state->player_y, state->player_x, init_data) && \ + state->map[state->player_y][state->player_x] == ' ') { + + state->map[state->player_y][state->player_x] = '.'; } + state->player_x++; } + return true; } -bool push_box_up(sokoban_t* init_data,state_t* state) -{ - if (state->map[state->player_y-2][state->player_x] == '$' || state->map[state->player_y-2][state->player_x] == '*') { +bool push_box_up(sokoban_t *init_data, state_t *state) { + if (state->map[state->player_y-2][state->player_x] == '$' || \ + state->map[state->player_y-2][state->player_x] == '*') { + return false; } else if (state->map[state->player_y-2][state->player_x] == '#') { return false; } else { state->map[state->player_y-1][state->player_x] = '@'; - if(state->map[state->player_y-2][state->player_x] == '.') + if (state->map[state->player_y-2][state->player_x] == '.') { state->map[state->player_y-2][state->player_x] = '*'; - else + } else { state->map[state->player_y-2][state->player_x] = '$'; + } state->map[state->player_y][state->player_x] = ' '; - if (is_goal_loc( state->player_y, state->player_x, init_data) && state->map[state->player_y][state->player_x] == ' ') { - state->map[state->player_y][state->player_x] = '.'; + + if (is_goal_loc(state->player_y, state->player_x, init_data) && \ + state->map[state->player_y][state->player_x] == ' ') { + + state->map[state->player_y][state->player_x] = '.'; } + state->player_y--; } + return true; } -bool push_box_down(sokoban_t* init_data,state_t* state) -{ - if (state->map[state->player_y+2][state->player_x] == '$' || state->map[state->player_y+2][state->player_x] == '*') { +bool push_box_down(sokoban_t *init_data, state_t *state) { + if (state->map[state->player_y+2][state->player_x] == '$' || \ + state->map[state->player_y+2][state->player_x] == '*') { + return false; } else if (state->map[state->player_y+2][state->player_x] == '#') { return false; } else { - state->map[state->player_y+1][state->player_x] = '@'; - if(state->map[state->player_y+2][state->player_x] == '.') + if (state->map[state->player_y+2][state->player_x] == '.') { state->map[state->player_y+2][state->player_x] = '*'; - else + } else { state->map[state->player_y+2][state->player_x] = '$'; + } state->map[state->player_y][state->player_x] = ' '; - if (is_goal_loc( state->player_y, state->player_x, init_data) && state->map[state->player_y][state->player_x] == ' ') { - state->map[state->player_y][state->player_x] = '.'; + + if (is_goal_loc(state->player_y, state->player_x, init_data) && \ + state->map[state->player_y][state->player_x] == ' ') { + + state->map[state->player_y][state->player_x] = '.'; } + state->player_y++; } + return true; } - - /************************************** * Player Moves given a state state * ***************************************/ -bool move_left_player(sokoban_t* init_data,state_t* state) -{ +bool move_left_player(sokoban_t *init_data, state_t *state) { if (state->map[state->player_y][state->player_x-1] != '#') { - if (state->map[state->player_y][state->player_x-1] == '$' || state->map[state->player_y][state->player_x-1] == '*') { + if (state->map[state->player_y][state->player_x-1] == '$' || \ + state->map[state->player_y][state->player_x-1] == '*') { + return push_box_left(init_data, state); } else { state->map[state->player_y][state->player_x-1] = '@'; state->map[state->player_y][state->player_x] = ' '; - if (is_goal_loc( state->player_y, state->player_x, init_data) && state->map[state->player_y][state->player_x] == ' ') { + + if (is_goal_loc(state->player_y, state->player_x, init_data) && \ + state->map[state->player_y][state->player_x] == ' ') { + state->map[state->player_y][state->player_x] = '.'; } + state->player_x--; + return true; } } + return false; } -bool move_right_player(sokoban_t* init_data,state_t* state) -{ +bool move_right_player(sokoban_t *init_data, state_t *state) { if (state->map[state->player_y][state->player_x+1] != '#') { - if (state->map[state->player_y][state->player_x+1] == '$' || state->map[state->player_y][state->player_x+1] == '*') { + if (state->map[state->player_y][state->player_x+1] == '$' || \ + state->map[state->player_y][state->player_x+1] == '*') { + return push_box_right(init_data, state); } else { state->map[state->player_y][state->player_x+1] = '@'; state->map[state->player_y][state->player_x] = ' '; - if (is_goal_loc( state->player_y, state->player_x, init_data) && state->map[state->player_y][state->player_x] == ' ') { + + if (is_goal_loc(state->player_y, state->player_x, init_data) && \ + state->map[state->player_y][state->player_x] == ' ') { + state->map[state->player_y][state->player_x] = '.'; } + state->player_x++; + return true; } } + return false; } -bool move_up_player(sokoban_t* init_data,state_t* state) -{ +bool move_up_player(sokoban_t *init_data, state_t *state) { if (state->map[state->player_y-1][state->player_x] != '#') { - if (state->map[state->player_y-1][state->player_x] == '$' || state->map[state->player_y-1][state->player_x] == '*') { + if (state->map[state->player_y-1][state->player_x] == '$' || \ + state->map[state->player_y-1][state->player_x] == '*') { + return push_box_up(init_data, state); } else { state->map[state->player_y-1][state->player_x] = '@'; state->map[state->player_y][state->player_x] = ' '; - if (is_goal_loc( state->player_y, state->player_x, init_data) && state->map[state->player_y][state->player_x] == ' ') { + + if (is_goal_loc(state->player_y, state->player_x, init_data) && \ + state->map[state->player_y][state->player_x] == ' ') { + state->map[state->player_y][state->player_x] = '.'; } + state->player_y--; + return true; } - } + } + return false; } -bool move_down_player(sokoban_t* init_data,state_t* state) -{ +bool move_down_player(sokoban_t *init_data, state_t *state) { if (state->map[state->player_y+1][state->player_x] != '#') { - if (state->map[state->player_y+1][state->player_x] == '$' || state->map[state->player_y+1][state->player_x] == '*') { + if (state->map[state->player_y+1][state->player_x] == '$' || \ + state->map[state->player_y+1][state->player_x] == '*') { + return push_box_down(init_data, state); } else { state->map[state->player_y+1][state->player_x] = '@'; state->map[state->player_y][state->player_x] = ' '; - if (is_goal_loc( state->player_y, state->player_x, init_data) && state->map[state->player_y][state->player_x] == ' ') { + + if (is_goal_loc(state->player_y, state->player_x, init_data) && \ + state->map[state->player_y][state->player_x] == ' ') { + state->map[state->player_y][state->player_x] = '.'; } + state->player_y++; + return true; } } + return false; } - -bool execute_move_t(sokoban_t* init_data, state_t* state, move_t move) { - +bool execute_move_t(sokoban_t *init_data, state_t *state, move_t move) { bool player_moved = false; - //Determine which button is pushed + // Determine which button is pushed switch (move) { - case up: - player_moved = move_up_player(init_data, state); - break; + case up: + player_moved = move_up_player(init_data, state); + break; - case down: - player_moved = move_down_player(init_data, state); - break; + case down: + player_moved = move_down_player(init_data, state); + break; - case left: - player_moved = move_left_player(init_data, state); - break; - - case right: - player_moved = move_right_player(init_data, state); - break; + case left: + player_moved = move_left_player(init_data, state); + break; + case right: + player_moved = move_right_player(init_data, state); + break; } return player_moved; - - } /***************************************************************************** * Function: simple_corner_deadlock * -* Parameters: sokoban_t* init_data, state_t* state * +* Parameters: sokoban_t *init_data, state_t *state * * Returns: bool * * Description: Check if box has been pusehd into a loc in a corner wall * * and loc != destination * *****************************************************************************/ - -bool corner_check(int x, int y, sokoban_t* init_data, state_t* state){ +bool corner_check(int x, int y, sokoban_t *init_data, state_t *state) { // Check if corner if (((state->map[y][x+1] == '#' && state->map[y+1][x] == '#') || (state->map[y+1][x] == '#' && state->map[y][x-1] == '#') || (state->map[y][x-1] == '#' && state->map[y-1][x] == '#') || (state->map[y-1][x] == '#' && state->map[y][x+1] == '#')) && - !is_goal_loc( state->player_y, state->player_x, init_data) ) { + !is_goal_loc(state->player_y, state->player_x, init_data)) { + return true; } return false; } -bool simple_corner_deadlock(sokoban_t* init_data, state_t* state) -{ +bool simple_corner_deadlock(sokoban_t *init_data, state_t *state) { bool deadlock = false; int x = state->player_x; int y = state->player_y; - if (state->map[state->player_y + 1][state->player_x] == '$'){ + if (state->map[state->player_y + 1][state->player_x] == '$') { y = state->player_y + 1; deadlock = corner_check(x, y, init_data, state); } - if( state->map[state->player_y-1][state->player_x] == '$'){ + + if (state->map[state->player_y-1][state->player_x] == '$') { y = state->player_y - 1; deadlock = corner_check(x, y, init_data, state); } - if( state->map[state->player_y][state->player_x+1] == '$'){ + + if (state->map[state->player_y][state->player_x+1] == '$') { x = state->player_x + 1; deadlock = corner_check(x, y, init_data, state); } - if( state->map[state->player_y][state->player_x-1] == '$'){ + + if (state->map[state->player_y][state->player_x-1] == '$') { x = state->player_x - 1; deadlock = corner_check(x, y, init_data, state); } @@ -258,46 +318,36 @@ bool simple_corner_deadlock(sokoban_t* init_data, state_t* state) return deadlock; } - /***************************************************************************** * Function: winning_condition * -* Parameters: sokoban_t* init_data, state_t* state * +* Parameters: sokoban_t *init_data, state_t *state * * Returns: bool * * Description: Check if all boxes are in a destination * *****************************************************************************/ - -bool winning_condition(sokoban_t* init_data, state_t* state) -{ - +bool winning_condition(sokoban_t *init_data, state_t *state) { for (int y = 0; y < init_data->lines; y++) { - for (int x = 0; init_data->map_save[y][x] != '\0'; x++) { - if (state->map[y][x] == '$') - return false; - } + for (int x = 0; init_data->map_save[y][x] != '\0'; x++) { + if (state->map[y][x] == '$') { + return false; + } + } } return true; - } -/********* -* MACROS * -*********/ -#include -#define TERMINAL_TYPE (strcmp(getenv("TERM"), "xterm") == 0 ? "rxvt" : \ - getenv("TERM")) - -void play_solution( sokoban_t init_data, char* solution ){ - +void play_solution(sokoban_t init_data, char *solution) { SCREEN *mainScreen = newterm(TERMINAL_TYPE, stdout, stdin); set_term(mainScreen); int cols = 1; - for(int i = 0; i < init_data.lines; i++){ - if(strlen(init_data.map[i]) > (size_t) cols){ + + for (int i = 0; i < init_data.lines; i++) { + if (strlen(init_data.map[i]) > (size_t) cols) { cols = strlen(init_data.map[i]); } } + WINDOW *mainWindow = newwin(init_data.lines, cols, 0, 0); cbreak(); @@ -310,24 +360,29 @@ void play_solution( sokoban_t init_data, char* solution ){ wnoutrefresh(mainWindow); doupdate(); refresh(); - for (int i = 0; i < init_data.lines; i++) + + for (int i = 0; i < init_data.lines; i++) { mvprintw(i, 0, init_data.map[i]); + } move(init_data.player_y, init_data.player_x); int key_pressed = 0; - if( solution[i] == 'u' || solution[i] == 'U') + if (solution[i] == 'u' || solution[i] == 'U') { key_pressed = KEY_UP; - else if( solution[i] == 'd' || solution[i] == 'D') - key_pressed = KEY_DOWN; - else if( solution[i] == 'l' || solution[i] == 'L') - key_pressed = KEY_LEFT; - else if( solution[i] == 'r' || solution[i] == 'R') - key_pressed = KEY_RIGHT; + } else if (solution[i] == 'd' || solution[i] == 'D') { + key_pressed = KEY_DOWN; + } else if (solution[i] == 'l' || solution[i] == 'L') { + key_pressed = KEY_LEFT; + } else if (solution[i] == 'r' || solution[i] == 'R') { + key_pressed = KEY_RIGHT; + } + init_data = key_check(init_data, key_pressed); init_data = check_zone_reset(init_data); usleep(500000); } + touchwin(mainWindow); wnoutrefresh(mainWindow); doupdate(); @@ -335,12 +390,12 @@ void play_solution( sokoban_t init_data, char* solution ){ usleep(1500000); } -void print_map(sokoban_t* init_data, state_t* state ){ +void print_map(sokoban_t *init_data, state_t *state) { initscr(); cbreak(); noecho(); clear(); - for (int i = 0; i < init_data->lines; i++){ + for (int i = 0; i < init_data->lines; i++) { mvprintw(i, 0, state->map[i]); move(state->player_y, state->player_x); } diff --git a/src/ai/utils.h b/src/ai/utils.h index 165c017..b769885 100644 --- a/src/ai/utils.h +++ b/src/ai/utils.h @@ -1,15 +1,16 @@ #ifndef __UTILS__ #define __UTILS__ +#include +#include +#include #include #include #include -#include #include -#include -#include #include -#include +#include + #include "../../include/sokoban.h" #define SIZE 4 @@ -19,14 +20,11 @@ * Data structure containing the information about the game state * representing the state of the game. */ -struct state_s{ +typedef struct state_s{ char **map; int player_x; int player_y; -}; - -typedef struct state_s state_t; - +} state_t; /** * Move type @@ -38,15 +36,18 @@ typedef enum moves{ down=3 } move_t; - - - /** * Helper functions */ + bool execute_move_t(sokoban_t *init_data, state_t *state, move_t move); + bool simple_corner_deadlock(sokoban_t *init_data, state_t *state); + bool winning_condition(sokoban_t *init_data, state_t *state); -void play_solution( sokoban_t init_data, char* solution ); + +void play_solution(sokoban_t init_data, char* solution); + void print_map(sokoban_t *init_data, state_t *state); + #endif diff --git a/src/ai/utils.o b/src/ai/utils.o index 76f5846..bcf4c54 100644 Binary files a/src/ai/utils.o and b/src/ai/utils.o differ diff --git a/src/find_player.c b/src/find_player.c index d324c87..77cfe8b 100644 --- a/src/find_player.c +++ b/src/find_player.c @@ -5,30 +5,32 @@ ** Function for finding the player on the map */ -#include -#include -#include #include +#include +#include +#include + #include "../include/libmy.h" #include "../include/sokoban.h" -sokoban_t find_player(sokoban_t sokoban) -{ +sokoban_t find_player(sokoban_t sokoban) { sokoban.player_x = 0; sokoban.player_y = 0; + for (int i = 0; i < sokoban.lines; i++) { for (int j = 0; sokoban.map[i][j] != '\0'; j++) { sokoban = check_if_player(sokoban, i, j); } } + return (sokoban); } -sokoban_t check_if_player(sokoban_t sokoban, int y, int x) -{ +sokoban_t check_if_player(sokoban_t sokoban, int y, int x) { if (sokoban.map[y][x] == '@') { sokoban.player_x = x; sokoban.player_y = y; } + return (sokoban); } diff --git a/src/find_player.o b/src/find_player.o index 37fd3b8..af2e445 100644 Binary files a/src/find_player.o and b/src/find_player.o differ diff --git a/src/helper.c b/src/helper.c index e93e77d..6b817d9 100644 --- a/src/helper.c +++ b/src/helper.c @@ -2,14 +2,14 @@ ** EPITECH PROJECT, 2017 ** PSU_my_sokoban_2017 ** File description: -** Main function for the my_sokoban +** Function for printing CLI usage */ #include + #include "../include/libmy.h" -int helper(void) -{ +int helper(void) { my_putstr("USAGE\n"); my_putstr(" ./sokoban <-s> map \n\n"); my_putstr("DESCRIPTION\n"); diff --git a/src/helper.o b/src/helper.o index 92fe570..84efedf 100644 Binary files a/src/helper.o and b/src/helper.o differ diff --git a/src/key_check.c b/src/key_check.c index 65f61ba..60cbbec 100644 --- a/src/key_check.c +++ b/src/key_check.c @@ -5,25 +5,34 @@ ** Function that manage key press for sokoban */ -#include -#include -#include #include +#include +#include +#include + #include "../include/libmy.h" #include "../include/sokoban.h" -sokoban_t key_check(sokoban_t sokoban, int key) -{ +sokoban_t key_check(sokoban_t sokoban, int key) { if (key == KEY_LEFT) { sokoban = move_left(sokoban); } - if (key == KEY_RIGHT) + + if (key == KEY_RIGHT) { sokoban = move_right(sokoban); - if (key == KEY_UP) + } + + if (key == KEY_UP) { sokoban = move_up(sokoban); - if (key == KEY_DOWN) + } + + if (key == KEY_DOWN) { sokoban = move_down(sokoban); - if (key == ' ') + } + + if (key == ' ') { play(sokoban.base_path); + } + return (sokoban); } diff --git a/src/key_check.o b/src/key_check.o index 941ce77..0fd9969 100644 Binary files a/src/key_check.o and b/src/key_check.o differ diff --git a/src/loose_check.c b/src/loose_check.c index 07da157..44a10c2 100644 --- a/src/loose_check.c +++ b/src/loose_check.c @@ -5,37 +5,42 @@ ** Functions used to check if the game is loosed */ -#include -#include -#include #include +#include +#include +#include + #include "../include/libmy.h" #include "../include/sokoban.h" -void loose_check(sokoban_t sokoban) -{ - if( sokoban.map[sokoban.player_y+1][sokoban.player_x] == '$') - storage_loose_check(sokoban.player_y+1, sokoban.player_x, sokoban); - if( sokoban.map[sokoban.player_y-1][sokoban.player_x] == '$') - storage_loose_check(sokoban.player_y-1, sokoban.player_x, sokoban); - if( sokoban.map[sokoban.player_y][sokoban.player_x+1] == '$') - storage_loose_check(sokoban.player_y, sokoban.player_x+1, sokoban); - if( sokoban.map[sokoban.player_y][sokoban.player_x-1] == '$') - storage_loose_check(sokoban.player_y, sokoban.player_x-1, sokoban); +void loose_check(sokoban_t sokoban) { + if (sokoban.map[sokoban.player_y + 1][sokoban.player_x] == '$') { + storage_loose_check(sokoban.player_y + 1, sokoban.player_x, sokoban); + } + if (sokoban.map[sokoban.player_y - 1][sokoban.player_x] == '$') { + storage_loose_check(sokoban.player_y - 1, sokoban.player_x, sokoban); + } + + if (sokoban.map[sokoban.player_y][sokoban.player_x + 1] == '$') { + storage_loose_check(sokoban.player_y, sokoban.player_x + 1, sokoban); + } + + if (sokoban.map[sokoban.player_y][sokoban.player_x - 1] == '$') { + storage_loose_check(sokoban.player_y, sokoban.player_x - 1, sokoban); + } } -void storage_loose_check(int y, int x, sokoban_t sokoban) -{ +void storage_loose_check(int y, int x, sokoban_t sokoban) { if (sokoban.map[y][x] == '$') { if (((sokoban.map[y][x+1] == '#' && sokoban.map[y+1][x] == '#') || - (sokoban.map[y+1][x] == '#' && sokoban.map[y][x-1] == '#') || - (sokoban.map[y][x-1] == '#' && sokoban.map[y-1][x] == '#') || - (sokoban.map[y-1][x] == '#' && sokoban.map[y][x+1] == '#')) && - !is_goal_cell(y, x, sokoban ) ) { + (sokoban.map[y+1][x] == '#' && sokoban.map[y][x-1] == '#') || + (sokoban.map[y][x-1] == '#' && sokoban.map[y-1][x] == '#') || + (sokoban.map[y-1][x] == '#' && sokoban.map[y][x+1] == '#')) && + !is_goal_cell(y, x, sokoban ) ) { + endwin(); exit (1); } } } - diff --git a/src/loose_check.o b/src/loose_check.o index e7160ba..7d04ef8 100644 Binary files a/src/loose_check.o and b/src/loose_check.o differ diff --git a/src/main.c b/src/main.c index d370ea9..8bec272 100644 --- a/src/main.c +++ b/src/main.c @@ -5,29 +5,32 @@ ** Main function for the my_sokoban */ -#include -#include #include +#include #include +#include + #include "../include/libmy.h" #include "../include/sokoban.h" #include "ai/ai.h" -int main(int argc, char const **argv) -{ - if (argc < 2 || argc > 4) +int main(int argc, char const **argv) { + if (argc < 2 || argc > 4) { return (84); - if (argv[1][0] == '-' && argv[1][1] == 'h') + } + + if (argv[1][0] == '-' && argv[1][1] == 'h') { return(helper()); - else if (argv[1][0] == '-' && argv[1][1] == 's'){ + } else if (argv[1][0] == '-' && argv[1][1] == 's') { bool show_solution = false; - if (argc > 3 && strcmp(argv[3], "play_solution") == 0) + if (argc > 3 && strcmp(argv[3], "play_solution") == 0) { show_solution = true; + } solve(argv[2], show_solution); return 0; - } - else if (argv[1][0] != '-') + } else if (argv[1][0] != '-') { return(play(argv[1])); + } return (84); } diff --git a/src/main.o b/src/main.o index 10208f8..aba0412 100644 Binary files a/src/main.o and b/src/main.o differ diff --git a/src/map_check.c b/src/map_check.c index f9b9db0..5a24085 100644 --- a/src/map_check.c +++ b/src/map_check.c @@ -5,56 +5,53 @@ ** Function used to check if a map is valid or not */ -#include -#include #include +#include +#include + #include "../include/libmy.h" #include "../include/sokoban.h" -void map_check(sokoban_t sokoban) -{ - +void map_check(sokoban_t sokoban) { int player = 0; for (int i = 0; i < sokoban.lines; i++) { for (int j = 0; sokoban.map_save[i][j] != '\0'; j++) { - check_tile(i, j, sokoban); player += count_player(i, j, sokoban); } } - } -int check_tile(int y, int x, sokoban_t sokoban) -{ - if (sokoban.map_save[y][x] != '@' && sokoban.map_save[y][x] != '$' - && sokoban.map_save[y][x] != '#' && sokoban.map_save[y][x] != ' ' - && sokoban.map_save[y][x] != '\n' && sokoban.map_save[y][x] != '.' - && sokoban.map_save[y][x] != '+' && sokoban.map_save[y][x] != '*') - { +int check_tile(int y, int x, sokoban_t sokoban) { + if (sokoban.map_save[y][x] != '@' && sokoban.map_save[y][x] != '$' && \ + sokoban.map_save[y][x] != '#' && sokoban.map_save[y][x] != ' ' && \ + sokoban.map_save[y][x] != '\n' && sokoban.map_save[y][x] != '.' && \ + sokoban.map_save[y][x] != '+' && sokoban.map_save[y][x] != '*') { + write(2, "Unknown read character in map\n", 26); exit(84); } + return (0); } -int count_case_number(int y, int x, sokoban_t sokoban) -{ +int count_case_number(int y, int x, sokoban_t sokoban) { int i = 0; if (sokoban.map_save[y][x] == '$') { i++; } + return (i); } -int count_player(int y, int x, sokoban_t sokoban) -{ +int count_player(int y, int x, sokoban_t sokoban) { int i = 0; if (sokoban.map_save[y][x] == '@') { i++; } + return (i); } diff --git a/src/map_check.o b/src/map_check.o index b619ee3..5da307c 100644 Binary files a/src/map_check.o and b/src/map_check.o differ diff --git a/src/map_reading.c b/src/map_reading.c index bda1459..5f4c331 100644 --- a/src/map_reading.c +++ b/src/map_reading.c @@ -5,15 +5,15 @@ ** Main function for the my_sokoban */ -#include -#include -#include #include +#include +#include +#include + #include "../include/libmy.h" #include "../include/sokoban.h" -char *open_map(char const *path) -{ +char *open_map(char const *path) { int reading; char *buffer; @@ -22,58 +22,63 @@ char *open_map(char const *path) write(2, "No such file or directory\n", 26); exit (84); } + buffer = read_map(reading); close(reading); return (buffer); } -char *read_map(int reading) -{ +char *read_map(int reading) { char *buffer = malloc(sizeof(char) * 10000); int size = 32; size = read(reading, buffer, 10000); - if (size == -1) + if (size == -1) { exit(84); + } + buffer[size] = '\0'; return (buffer); } -int count_columns(sokoban_t sokoban, int position) -{ +int count_columns(sokoban_t sokoban, int position) { int columns = 0; for (; sokoban.buffer[position] != '\n'; position++) { columns++; } + return (columns); } -sokoban_t count_lines(sokoban_t sokoban) -{ +sokoban_t count_lines(sokoban_t sokoban) { sokoban.lines = 0; for (int i = 0; sokoban.buffer[i] != '\0'; i++) { - if (sokoban.buffer[i] == '\n' || sokoban.buffer[i] == '\0') - sokoban.lines++; + if (sokoban.buffer[i] == '\n' || sokoban.buffer[i] == '\0') { + sokoban.lines += 1; + } } + return (sokoban); } -sokoban_t make_map(char const *path, sokoban_t sokoban) -{ - sokoban.buffer = open_map(path); - sokoban = count_lines(sokoban); +sokoban_t make_map(char const *path, sokoban_t sokoban) { int k = 0; int columns = 0; + + sokoban.buffer = open_map(path); + sokoban = count_lines(sokoban); sokoban.num_chars_map = 0; sokoban.map = malloc(sizeof(char *) * sokoban.lines); sokoban.map_save = malloc(sizeof (char *) * sokoban.lines); + for (int j = 0; j < sokoban.lines; j++) { columns = count_columns(sokoban, k); sokoban.num_chars_map += columns; sokoban.map[j] = malloc(sizeof(char) * columns + 1); sokoban.map_save[j] = malloc(sizeof(char) * columns + 1); + for (int i = 0; i < columns; i++) { sokoban.map[j][i] = sokoban.buffer[k]; sokoban.map_save[j][i] = sokoban.buffer[k]; @@ -81,12 +86,14 @@ sokoban_t make_map(char const *path, sokoban_t sokoban) sokoban.map_save[j][i+1] = '\0'; k++; } + k++; } + return (sokoban); } -int is_goal_cell(int y, int x, sokoban_t sokoban) -{ - return (sokoban.map_save[y][x] == '.') || (sokoban.map_save[y][x] == '+') || (sokoban.map_save[y][x] == '*'); +int is_goal_cell(int y, int x, sokoban_t sokoban) { + return (sokoban.map_save[y][x] == '.') || \ + (sokoban.map_save[y][x] == '+') || (sokoban.map_save[y][x] == '*'); } diff --git a/src/map_reading.o b/src/map_reading.o index df7832a..a38c8ff 100644 Binary files a/src/map_reading.o and b/src/map_reading.o differ diff --git a/src/movement.c b/src/movement.c index 62f7a8c..8985861 100644 --- a/src/movement.c +++ b/src/movement.c @@ -5,148 +5,166 @@ ** Function that make the player move */ -#include -#include -#include #include +#include +#include +#include + #include "../include/libmy.h" #include "../include/sokoban.h" +sokoban_t move_box_left(sokoban_t sokoban) { + if (sokoban.map[sokoban.player_y][sokoban.player_x - 2] == '$' || \ + sokoban.map[sokoban.player_y][sokoban.player_x - 2] == '*') { -sokoban_t move_box_left(sokoban_t sokoban) -{ - if (sokoban.map[sokoban.player_y][sokoban.player_x-2] == '$' || sokoban.map[sokoban.player_y][sokoban.player_x-2] == '*') { return (sokoban); - } else if (sokoban.map[sokoban.player_y][sokoban.player_x-2] == '#') { + } else if (sokoban.map[sokoban.player_y][sokoban.player_x - 2] == '#') { return (sokoban); } else { - sokoban.map[sokoban.player_y][sokoban.player_x-1] = '@'; + sokoban.map[sokoban.player_y][sokoban.player_x - 1] = '@'; - if(sokoban.map[sokoban.player_y][sokoban.player_x-2] == '.') - sokoban.map[sokoban.player_y][sokoban.player_x-2] = '*'; - else - sokoban.map[sokoban.player_y][sokoban.player_x-2] = '$'; + if (sokoban.map[sokoban.player_y][sokoban.player_x - 2] == '.') { + sokoban.map[sokoban.player_y][sokoban.player_x - 2] = '*'; + } else { + sokoban.map[sokoban.player_y][sokoban.player_x - 2] = '$'; + } sokoban.map[sokoban.player_y][sokoban.player_x] = ' '; sokoban.player_x--; } + return (sokoban); } -sokoban_t move_box_right(sokoban_t sokoban) -{ - if (sokoban.map[sokoban.player_y][sokoban.player_x+2] == '$' || sokoban.map[sokoban.player_y][sokoban.player_x+2] == '*') { +sokoban_t move_box_right(sokoban_t sokoban) { + if (sokoban.map[sokoban.player_y][sokoban.player_x + 2] == '$' || \ + sokoban.map[sokoban.player_y][sokoban.player_x + 2] == '*') { + return (sokoban); - } else if (sokoban.map[sokoban.player_y][sokoban.player_x+2] == '#') { + } else if (sokoban.map[sokoban.player_y][sokoban.player_x + 2] == '#') { return (sokoban); } else { - sokoban.map[sokoban.player_y][sokoban.player_x+1] = '@'; + sokoban.map[sokoban.player_y][sokoban.player_x + 1] = '@'; - if(sokoban.map[sokoban.player_y][sokoban.player_x+2] == '.') - sokoban.map[sokoban.player_y][sokoban.player_x+2] = '*'; - else - sokoban.map[sokoban.player_y][sokoban.player_x+2] = '$'; + if (sokoban.map[sokoban.player_y][sokoban.player_x + 2] == '.') { + sokoban.map[sokoban.player_y][sokoban.player_x + 2] = '*'; + } else { + sokoban.map[sokoban.player_y][sokoban.player_x + 2] = '$'; + } sokoban.map[sokoban.player_y][sokoban.player_x] = ' '; sokoban.player_x++; } + return (sokoban); } -sokoban_t move_box_up(sokoban_t sokoban) -{ - if (sokoban.map[sokoban.player_y-2][sokoban.player_x] == '$' || sokoban.map[sokoban.player_y-2][sokoban.player_x] == '*') { +sokoban_t move_box_up(sokoban_t sokoban) { + if (sokoban.map[sokoban.player_y - 2][sokoban.player_x] == '$' || \ + sokoban.map[sokoban.player_y - 2][sokoban.player_x] == '*') { + return (sokoban); - } else if (sokoban.map[sokoban.player_y-2][sokoban.player_x] == '#') { + } else if (sokoban.map[sokoban.player_y - 2][sokoban.player_x] == '#') { return (sokoban); } else { - sokoban.map[sokoban.player_y-1][sokoban.player_x] = '@'; + sokoban.map[sokoban.player_y - 1][sokoban.player_x] = '@'; - if(sokoban.map[sokoban.player_y-2][sokoban.player_x] == '.') - sokoban.map[sokoban.player_y-2][sokoban.player_x] = '*'; - else - sokoban.map[sokoban.player_y-2][sokoban.player_x] = '$'; + if (sokoban.map[sokoban.player_y - 2][sokoban.player_x] == '.') { + sokoban.map[sokoban.player_y - 2][sokoban.player_x] = '*'; + } else { + sokoban.map[sokoban.player_y - 2][sokoban.player_x] = '$'; + } sokoban.map[sokoban.player_y][sokoban.player_x] = ' '; sokoban.player_y--; } + return (sokoban); } -sokoban_t move_box_down(sokoban_t sokoban) -{ - if (sokoban.map[sokoban.player_y+2][sokoban.player_x] == '$' || sokoban.map[sokoban.player_y+2][sokoban.player_x] == '*') { +sokoban_t move_box_down(sokoban_t sokoban) { + if (sokoban.map[sokoban.player_y + 2][sokoban.player_x] == '$' || \ + sokoban.map[sokoban.player_y + 2][sokoban.player_x] == '*') { + return (sokoban); - } else if (sokoban.map[sokoban.player_y+2][sokoban.player_x] == '#') { + } else if (sokoban.map[sokoban.player_y + 2][sokoban.player_x] == '#') { return (sokoban); } else { - sokoban.map[sokoban.player_y+1][sokoban.player_x] = '@'; + sokoban.map[sokoban.player_y + 1][sokoban.player_x] = '@'; - if(sokoban.map[sokoban.player_y+2][sokoban.player_x] == '.') - sokoban.map[sokoban.player_y+2][sokoban.player_x] = '*'; - else - sokoban.map[sokoban.player_y+2][sokoban.player_x] = '$'; - + if (sokoban.map[sokoban.player_y + 2][sokoban.player_x] == '.') { + sokoban.map[sokoban.player_y + 2][sokoban.player_x] = '*'; + } else { + sokoban.map[sokoban.player_y + 2][sokoban.player_x] = '$'; + } sokoban.map[sokoban.player_y][sokoban.player_x] = ' '; sokoban.player_y++; } + return (sokoban); } - -sokoban_t move_left(sokoban_t sokoban) -{ - if (sokoban.map[sokoban.player_y][sokoban.player_x-1] != '#') { - if (sokoban.map[sokoban.player_y][sokoban.player_x-1] == '$' || sokoban.map[sokoban.player_y][sokoban.player_x-1] == '*') { +sokoban_t move_left(sokoban_t sokoban) { + if (sokoban.map[sokoban.player_y][sokoban.player_x - 1] != '#') { + if (sokoban.map[sokoban.player_y][sokoban.player_x - 1] == '$' || \ + sokoban.map[sokoban.player_y][sokoban.player_x - 1] == '*') { + sokoban = move_box_left(sokoban); } else { - sokoban.map[sokoban.player_y][sokoban.player_x-1] = '@'; + sokoban.map[sokoban.player_y][sokoban.player_x - 1] = '@'; sokoban.map[sokoban.player_y][sokoban.player_x] = ' '; sokoban.player_x--; } } + return (sokoban); } -sokoban_t move_right(sokoban_t sokoban) -{ - if (sokoban.map[sokoban.player_y][sokoban.player_x+1] != '#') { - if (sokoban.map[sokoban.player_y][sokoban.player_x+1] == '$' || sokoban.map[sokoban.player_y][sokoban.player_x+1] == '*') { +sokoban_t move_right(sokoban_t sokoban) { + if (sokoban.map[sokoban.player_y][sokoban.player_x + 1] != '#') { + if (sokoban.map[sokoban.player_y][sokoban.player_x + 1] == '$' || \ + sokoban.map[sokoban.player_y][sokoban.player_x + 1] == '*') { + sokoban = move_box_right(sokoban); } else { - sokoban.map[sokoban.player_y][sokoban.player_x+1] = '@'; + sokoban.map[sokoban.player_y][sokoban.player_x + 1] = '@'; sokoban.map[sokoban.player_y][sokoban.player_x] = ' '; sokoban.player_x++; } } + return (sokoban); } -sokoban_t move_up(sokoban_t sokoban) -{ - if (sokoban.map[sokoban.player_y-1][sokoban.player_x] != '#') { - if (sokoban.map[sokoban.player_y-1][sokoban.player_x] == '$' || sokoban.map[sokoban.player_y-1][sokoban.player_x] == '*') { +sokoban_t move_up(sokoban_t sokoban) { + if (sokoban.map[sokoban.player_y - 1][sokoban.player_x] != '#') { + if (sokoban.map[sokoban.player_y - 1][sokoban.player_x] == '$' || \ + sokoban.map[sokoban.player_y - 1][sokoban.player_x] == '*') { + sokoban = move_box_up(sokoban); } else { - sokoban.map[sokoban.player_y-1][sokoban.player_x] = '@'; + sokoban.map[sokoban.player_y - 1][sokoban.player_x] = '@'; sokoban.map[sokoban.player_y][sokoban.player_x] = ' '; sokoban.player_y--; } } + return (sokoban); } -sokoban_t move_down(sokoban_t sokoban) -{ - if (sokoban.map[sokoban.player_y+1][sokoban.player_x] != '#') { - if (sokoban.map[sokoban.player_y+1][sokoban.player_x] == '$' || sokoban.map[sokoban.player_y+1][sokoban.player_x] == '*') { +sokoban_t move_down(sokoban_t sokoban) { + if (sokoban.map[sokoban.player_y + 1][sokoban.player_x] != '#') { + if (sokoban.map[sokoban.player_y + 1][sokoban.player_x] == '$' || \ + sokoban.map[sokoban.player_y + 1][sokoban.player_x] == '*') { + sokoban = move_box_down(sokoban); } else { - sokoban.map[sokoban.player_y+1][sokoban.player_x] = '@'; + sokoban.map[sokoban.player_y + 1][sokoban.player_x] = '@'; sokoban.map[sokoban.player_y][sokoban.player_x] = ' '; sokoban.player_y++; } } + return (sokoban); } diff --git a/src/movement.o b/src/movement.o index 109e4b4..3bf7821 100644 Binary files a/src/movement.o and b/src/movement.o differ diff --git a/src/play.c b/src/play.c index 02a5d46..62e6514 100644 --- a/src/play.c +++ b/src/play.c @@ -7,50 +7,45 @@ ** Adapted by Nir Lipo, 2021 */ -#include -#include -#include #include +#include +#include +#include +#include + #include "../include/libmy.h" #include "../include/sokoban.h" /********* * MACROS * *********/ -#include + #define TERMINAL_TYPE (strcmp(getenv("TERM"), "xterm") == 0 ? "rxvt" : \ getenv("TERM")) SCREEN *mainScreen = NULL; WINDOW *mainWindow = NULL; - -int play(char const *path) -{ - /** - * Load Map - */ +int play(char const *path) { + // Load map sokoban_t sokoban = make_map(path, sokoban); + sokoban.base_path = path; - /** - * Count number of boxes and Storage locations - */ + // Count number of boxes and Storage locations map_check(sokoban); - /** - * Locate player x,y position - */ + // Locate player x,y position sokoban = find_player(sokoban); - - sokoban.base_path = path; mainScreen = newterm(TERMINAL_TYPE, stdout, stdin); set_term(mainScreen); int cols = 1; - for(int i = 0; i < sokoban.lines; i++){ - if(strlen(sokoban.map[i]) > (size_t) cols){ + + for (int i = 0; i < sokoban.lines; i++) { + if (strlen(sokoban.map[i]) > (size_t) cols) { cols = strlen(sokoban.map[i]); } } + mainWindow = newwin(sokoban.lines, cols, 0, 0); cbreak(); @@ -63,18 +58,18 @@ int play(char const *path) touchwin(mainWindow); wnoutrefresh(mainWindow); doupdate(); - for (int i = 0; i < sokoban.lines; i++) + + for (int i = 0; i < sokoban.lines; i++) { mvprintw(i, 0, sokoban.map[i]); + } + move(sokoban.player_y, sokoban.player_x); sokoban = game_management(sokoban); } } -sokoban_t game_management(sokoban_t sokoban) -{ - int key_pressed = 0; - - key_pressed = getch(); +sokoban_t game_management(sokoban_t sokoban) { + int key_pressed = getch(); sokoban = key_check(sokoban, key_pressed); sokoban = check_zone_reset(sokoban); loose_check(sokoban); diff --git a/src/play.o b/src/play.o index 79e1141..10bd622 100644 Binary files a/src/play.o and b/src/play.o differ diff --git a/src/win_check.c b/src/win_check.c index f301590..a002448 100644 --- a/src/win_check.c +++ b/src/win_check.c @@ -5,23 +5,23 @@ ** Function that check if the game is won */ -#include -#include -#include #include +#include +#include +#include + #include "../include/libmy.h" #include "../include/sokoban.h" -void win_check(sokoban_t sokoban) -{ +void win_check(sokoban_t sokoban) { for (int i = 0; i < sokoban.lines; i++) { for (int j = 0; sokoban.map_save[i][j] != '\0'; j++) { - if (sokoban.map[i][j] == '$') - return ; + if (sokoban.map[i][j] == '$') { + return; + } } } endwin(); exit (0); - -} \ No newline at end of file +} diff --git a/src/win_check.o b/src/win_check.o index 413161b..9fa6380 100644 Binary files a/src/win_check.o and b/src/win_check.o differ diff --git a/src/zone_check.c b/src/zone_check.c index 6fc7c03..459512f 100644 --- a/src/zone_check.c +++ b/src/zone_check.c @@ -7,28 +7,25 @@ ** Adpated by Nir 2021 */ -#include -#include #include +#include +#include + #include "../include/libmy.h" #include "../include/sokoban.h" -sokoban_t check_zone_reset(sokoban_t sokoban) -{ - sokoban = reset_zone(sokoban.player_y+1, sokoban.player_x, sokoban); - sokoban = reset_zone(sokoban.player_y-1, sokoban.player_x, sokoban); - sokoban = reset_zone(sokoban.player_y, sokoban.player_x+1, sokoban); - sokoban = reset_zone(sokoban.player_y, sokoban.player_x-1, sokoban); +sokoban_t check_zone_reset(sokoban_t sokoban) { + sokoban = reset_zone(sokoban.player_y + 1, sokoban.player_x, sokoban); + sokoban = reset_zone(sokoban.player_y - 1, sokoban.player_x, sokoban); + sokoban = reset_zone(sokoban.player_y, sokoban.player_x + 1, sokoban); + sokoban = reset_zone(sokoban.player_y, sokoban.player_x - 1, sokoban); return (sokoban); } -sokoban_t reset_zone(int y, int x, sokoban_t sokoban) -{ - if ( is_goal_cell(y, x, sokoban ) && sokoban.map[y][x] == ' ') { +sokoban_t reset_zone(int y, int x, sokoban_t sokoban) { + if (is_goal_cell(y, x, sokoban ) && sokoban.map[y][x] == ' ') { sokoban.map[y][x] = '.'; - return(sokoban); } return (sokoban); } - diff --git a/src/zone_check.o b/src/zone_check.o index 4059b88..bfbb570 100644 Binary files a/src/zone_check.o and b/src/zone_check.o differ