Memory leak fixes, formatting changes

This commit is contained in:
Rory Healy 2021-10-21 20:02:57 +11:00
parent cf9d366133
commit ab01fa2878
43 changed files with 787 additions and 597 deletions

View file

@ -6,6 +6,7 @@
*/
#include <stdarg.h>
#ifndef LIBMY_H
#define LIBMY_H
void my_putchar(char c);

View file

@ -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

View file

@ -8,7 +8,6 @@
#include "../include/libmy.h"
#include <unistd.h>
void my_putchar(char c)
{
void my_putchar(char c) {
write(1, &c, 1);
}

Binary file not shown.

View file

@ -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);
}

Binary file not shown.

BIN
sokoban

Binary file not shown.

View file

@ -1 +1 @@
drdrdrdrrruuuuuulllllddrdrdrDulululldRdRdrdRRllululuurdrdrDululldRuuluurrrrrdddddrddlUUUUUUruLLLLLulDDdrdddrdRRlluluurdrDulldruluulldRuuurrrrrdddddrddlUUUUUUruLLLLLulDDdrdrdddRRlluurDldRuulululldRdRluuuurrrrrdddddrddlUUUUUUruLLLLLulDDdrdrdrddRluulululldRdRluuuurrrrrdddddrddlUUUUUUruLLLLLulDD
rrRlllllL

View file

@ -1,161 +1,166 @@
#include <time.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#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);
}

View file

@ -3,6 +3,7 @@
#include <stdint.h>
#include <unistd.h>
#include "node.h"
#include "priority_queue.h"

Binary file not shown.

View file

@ -3,22 +3,20 @@
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#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;
}
}
}
}

View file

@ -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 */
#endif

Binary file not shown.

View file

@ -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

View file

@ -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; i<h->count; ++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);
}
}

View file

@ -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 <stdio.h>
#include <stdlib.h>
#include <curses.h>
#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

Binary file not shown.

View file

@ -1,256 +1,316 @@
#include <curses.h>
#include <string.h>
#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 <string.h>
#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);
}

View file

@ -1,15 +1,16 @@
#ifndef __UTILS__
#define __UTILS__
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#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

Binary file not shown.

View file

@ -5,30 +5,32 @@
** Function for finding the player on the map
*/
#include <ncurses.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <ncurses.h>
#include <stdlib.h>
#include <unistd.h>
#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);
}

Binary file not shown.

View file

@ -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 <unistd.h>
#include "../include/libmy.h"
int helper(void)
{
int helper(void) {
my_putstr("USAGE\n");
my_putstr(" ./sokoban <-s> map <play_solution>\n\n");
my_putstr("DESCRIPTION\n");

Binary file not shown.

View file

@ -5,25 +5,34 @@
** Function that manage key press for sokoban
*/
#include <ncurses.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <ncurses.h>
#include <stdlib.h>
#include <unistd.h>
#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);
}

Binary file not shown.

View file

@ -5,37 +5,42 @@
** Functions used to check if the game is loosed
*/
#include <ncurses.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <ncurses.h>
#include <stdlib.h>
#include <unistd.h>
#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);
}
}
}

Binary file not shown.

View file

@ -5,29 +5,32 @@
** Main function for the my_sokoban
*/
#include <ncurses.h>
#include <unistd.h>
#include <fcntl.h>
#include <ncurses.h>
#include <stdlib.h>
#include <unistd.h>
#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);
}

Binary file not shown.

View file

@ -5,56 +5,53 @@
** Function used to check if a map is valid or not
*/
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#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);
}

Binary file not shown.

View file

@ -5,15 +5,15 @@
** Main function for the my_sokoban
*/
#include <ncurses.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <ncurses.h>
#include <stdlib.h>
#include <unistd.h>
#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] == '*');
}

Binary file not shown.

View file

@ -5,148 +5,166 @@
** Function that make the player move
*/
#include <ncurses.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <ncurses.h>
#include <stdlib.h>
#include <unistd.h>
#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);
}

Binary file not shown.

View file

@ -7,50 +7,45 @@
** Adapted by Nir Lipo, 2021
*/
#include <ncurses.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "../include/libmy.h"
#include "../include/sokoban.h"
/*********
* MACROS *
*********/
#include <string.h>
#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);

Binary file not shown.

View file

@ -5,23 +5,23 @@
** Function that check if the game is won
*/
#include <ncurses.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <ncurses.h>
#include <stdlib.h>
#include <unistd.h>
#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);
}
}

Binary file not shown.

View file

@ -7,28 +7,25 @@
** Adpated by Nir 2021
*/
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#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);
}

Binary file not shown.