Memory leak fixes, formatting changes
This commit is contained in:
parent
cf9d366133
commit
ab01fa2878
43 changed files with 787 additions and 597 deletions
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifndef LIBMY_H
|
||||
#define LIBMY_H
|
||||
void my_putchar(char c);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#ifndef BSQ_H
|
||||
#define BSQ_H
|
||||
|
||||
typedef struct sokoban {
|
||||
char *buffer;
|
||||
char **map;
|
||||
|
@ -19,31 +20,59 @@
|
|||
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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
BIN
lib/my_putchar.o
BIN
lib/my_putchar.o
Binary file not shown.
|
@ -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);
|
||||
}
|
||||
|
|
BIN
lib/my_putstr.o
BIN
lib/my_putstr.o
Binary file not shown.
BIN
sokoban
BIN
sokoban
Binary file not shown.
|
@ -1 +1 @@
|
|||
drdrdrdrrruuuuuulllllddrdrdrDulululldRdRdrdRRllululuurdrdrDululldRuuluurrrrrdddddrddlUUUUUUruLLLLLulDDdrdddrdRRlluluurdrDulldruluulldRuuurrrrrdddddrddlUUUUUUruLLLLLulDDdrdrdddRRlluurDldRuulululldRdRluuuurrrrrdddddrddlUUUUUUruLLLLLulDDdrdrdrddRluulululldRdRluuuurrrrrdddddrddlUUUUUUruLLLLLulDD
|
||||
rrRlllllL
|
||||
|
|
123
src/ai/ai.c
123
src/ai/ai.c
|
@ -1,13 +1,12 @@
|
|||
#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
|
||||
|
@ -16,9 +15,8 @@ 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] == '$')
|
||||
|
@ -47,11 +45,11 @@ char* save_solution( node_t* solution_node ){
|
|||
else
|
||||
solution_string[n->depth-1] = 'r';
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
n = n->parent;
|
||||
}
|
||||
|
||||
return solution_string;
|
||||
}
|
||||
|
||||
|
@ -60,11 +58,13 @@ char* save_solution( node_t* solution_node ){
|
|||
*/
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
@ -74,22 +74,23 @@ void copy_state(sokoban_t* init_data, state_t* dst, state_t* src){
|
|||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -102,14 +103,14 @@ node_t* create_node( sokoban_t* init_data, node_t* 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;
|
||||
|
||||
|
@ -120,29 +121,35 @@ bool applyAction(sokoban_t* init_data, node_t* n, node_t** new_node, move_t acti
|
|||
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
|
||||
|
||||
// 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 = realloc(expanded_nodes_table, \
|
||||
sizeof(node_t*) * expanded_nodes_table_size);
|
||||
}
|
||||
|
||||
expanded_nodes_table[ expanded_nodes ] = n;
|
||||
|
||||
}
|
||||
|
||||
void free_memory(unsigned expanded_nodes ){
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -150,10 +157,8 @@ void free_memory(unsigned expanded_nodes ){
|
|||
* Given a 2D map, returns a 1D 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++) {
|
||||
(*dst_map)[current_i] = src_map[i][j];
|
||||
|
@ -165,8 +170,7 @@ 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();
|
||||
|
||||
|
@ -187,8 +191,6 @@ void find_solution(sokoban_t* init_data, bool show_solution)
|
|||
// 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);
|
||||
|
||||
|
||||
|
||||
// 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));
|
||||
|
@ -207,10 +209,7 @@ void find_solution(sokoban_t* init_data, bool show_solution)
|
|||
// 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;
|
||||
|
@ -245,13 +250,13 @@ void find_solution(sokoban_t* init_data, bool show_solution)
|
|||
}
|
||||
}
|
||||
|
||||
//----------------------------
|
||||
|
||||
// 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,11 +264,22 @@ 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();
|
||||
|
@ -277,9 +293,9 @@ void find_solution(sokoban_t* init_data, bool show_solution)
|
|||
if (solution != NULL) {
|
||||
printf("\nSOLUTION: \n");
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
* Count number of boxes and Storage locations
|
||||
*/
|
||||
map_check(sokoban);
|
||||
|
||||
/**
|
||||
* Locate player x,y position
|
||||
*/
|
||||
sokoban = find_player(sokoban);
|
||||
|
||||
sokoban.base_path = path;
|
||||
|
||||
find_solution(&sokoban, show_solution);
|
||||
// Count number of boxes and Storage locations
|
||||
map_check(sokoban);
|
||||
|
||||
// Locate player x,y position
|
||||
sokoban = find_player(sokoban);
|
||||
|
||||
find_solution(&sokoban, show_solution);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "node.h"
|
||||
#include "priority_queue.h"
|
||||
|
||||
|
|
BIN
src/ai/ai.o
BIN
src/ai/ai.o
Binary file not shown.
|
@ -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,
|
||||
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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,22 +13,18 @@
|
|||
#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);
|
||||
|
||||
/****************** STRUCTURES ******************/
|
||||
|
@ -58,13 +54,13 @@ typedef struct HashTable {
|
|||
/****************** INTERFACE ******************/
|
||||
|
||||
/* Setup */
|
||||
int ht_setup(HashTable* table,
|
||||
size_t key_size,
|
||||
size_t value_size,
|
||||
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);
|
||||
|
||||
#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.
|
@ -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
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
|
||||
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++)
|
||||
|
||||
for (int i = 0; i < initial_size; i++) {
|
||||
h->heaparr[i] = NULL;
|
||||
}
|
||||
|
||||
if (!h->heaparr) {
|
||||
printf("Error allocatinga memory...\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void max_heapify(node_t **data, int loc, int count) {
|
||||
|
@ -24,10 +24,10 @@ void max_heapify(node_t** data, int loc, int count) {
|
|||
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;
|
||||
}
|
||||
|
@ -38,61 +38,71 @@ void max_heapify(node_t** data, int loc, int count) {
|
|||
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) {
|
||||
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 *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;
|
||||
if (temp == removed) {
|
||||
h->heaparr[0] = NULL;
|
||||
}
|
||||
|
||||
max_heapify(h->heaparr, 0, h->count);
|
||||
return removed;
|
||||
}
|
||||
|
@ -101,10 +111,6 @@ node_t* heap_delete(struct heap* h)
|
|||
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);
|
||||
free(n);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Binary file not shown.
203
src/ai/utils.c
203
src/ai/utils.c
|
@ -1,189 +1,250 @@
|
|||
#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] == ' ') {
|
||||
|
||||
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] == ' ') {
|
||||
|
||||
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] == ' ') {
|
||||
|
||||
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 player_moved = false;
|
||||
|
||||
// Determine which button is pushed
|
||||
|
@ -203,12 +264,9 @@ bool execute_move_t(sokoban_t* init_data, state_t* state, move_t move) {
|
|||
case right:
|
||||
player_moved = move_right_player(init_data, state);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return player_moved;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -219,7 +277,6 @@ bool execute_move_t(sokoban_t* init_data, state_t* state, move_t move) {
|
|||
* and loc != destination *
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
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] == '#') ||
|
||||
|
@ -227,13 +284,13 @@ bool corner_check(int x, int y, sokoban_t* init_data, state_t* state){
|
|||
(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)) {
|
||||
|
||||
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;
|
||||
|
@ -242,14 +299,17 @@ bool simple_corner_deadlock(sokoban_t* init_data, state_t* state)
|
|||
y = state->player_y + 1;
|
||||
deadlock = corner_check(x, y, init_data, state);
|
||||
}
|
||||
|
||||
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] == '$') {
|
||||
x = state->player_x + 1;
|
||||
deadlock = corner_check(x, y, init_data, state);
|
||||
}
|
||||
|
||||
if (state->map[state->player_y][state->player_x-1] == '$') {
|
||||
x = state->player_x - 1;
|
||||
deadlock = corner_check(x, y, init_data, state);
|
||||
|
@ -258,7 +318,6 @@ bool simple_corner_deadlock(sokoban_t* init_data, state_t* state)
|
|||
return deadlock;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Function: winning_condition *
|
||||
* Parameters: sokoban_t *init_data, state_t *state *
|
||||
|
@ -266,38 +325,29 @@ bool simple_corner_deadlock(sokoban_t* init_data, state_t* state)
|
|||
* 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] == '$')
|
||||
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) {
|
||||
|
||||
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) {
|
||||
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')
|
||||
} else if (solution[i] == 'd' || solution[i] == 'D') {
|
||||
key_pressed = KEY_DOWN;
|
||||
else if( solution[i] == 'l' || solution[i] == 'L')
|
||||
} else if (solution[i] == 'l' || solution[i] == 'L') {
|
||||
key_pressed = KEY_LEFT;
|
||||
else if( solution[i] == 'r' || solution[i] == 'R')
|
||||
} 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();
|
||||
|
|
|
@ -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 print_map(sokoban_t *init_data, state_t *state);
|
||||
|
||||
#endif
|
||||
|
|
BIN
src/ai/utils.o
BIN
src/ai/utils.o
Binary file not shown.
|
@ -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.
|
@ -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");
|
||||
|
|
BIN
src/helper.o
BIN
src/helper.o
Binary file not shown.
|
@ -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);
|
||||
}
|
||||
|
|
BIN
src/key_check.o
BIN
src/key_check.o
Binary file not shown.
|
@ -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] == '$')
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
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 ) ) {
|
||||
|
||||
endwin();
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
23
src/main.c
23
src/main.c
|
@ -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);
|
||||
}
|
||||
|
|
BIN
src/main.o
BIN
src/main.o
Binary file not shown.
|
@ -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);
|
||||
}
|
||||
|
|
BIN
src/map_check.o
BIN
src/map_check.o
Binary file not shown.
|
@ -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.
|
@ -5,100 +5,111 @@
|
|||
** 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] == '#') {
|
||||
return (sokoban);
|
||||
} else {
|
||||
sokoban.map[sokoban.player_y][sokoban.player_x - 1] = '@';
|
||||
|
||||
if(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
|
||||
} 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] == '#') {
|
||||
return (sokoban);
|
||||
} else {
|
||||
sokoban.map[sokoban.player_y][sokoban.player_x + 1] = '@';
|
||||
|
||||
if(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
|
||||
} 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] == '#') {
|
||||
return (sokoban);
|
||||
} else {
|
||||
sokoban.map[sokoban.player_y - 1][sokoban.player_x] = '@';
|
||||
|
||||
if(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
|
||||
} 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] == '#') {
|
||||
return (sokoban);
|
||||
} else {
|
||||
sokoban.map[sokoban.player_y + 1][sokoban.player_x] = '@';
|
||||
|
||||
if(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
|
||||
} 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)
|
||||
{
|
||||
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] == '*') {
|
||||
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] = '@';
|
||||
|
@ -106,13 +117,15 @@ sokoban_t move_left(sokoban_t sokoban)
|
|||
sokoban.player_x--;
|
||||
}
|
||||
}
|
||||
|
||||
return (sokoban);
|
||||
}
|
||||
|
||||
sokoban_t move_right(sokoban_t 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] == '*') {
|
||||
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] = '@';
|
||||
|
@ -120,13 +133,15 @@ sokoban_t move_right(sokoban_t sokoban)
|
|||
sokoban.player_x++;
|
||||
}
|
||||
}
|
||||
|
||||
return (sokoban);
|
||||
}
|
||||
|
||||
sokoban_t move_up(sokoban_t 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] == '*') {
|
||||
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] = '@';
|
||||
|
@ -134,13 +149,15 @@ sokoban_t move_up(sokoban_t sokoban)
|
|||
sokoban.player_y--;
|
||||
}
|
||||
}
|
||||
|
||||
return (sokoban);
|
||||
}
|
||||
|
||||
sokoban_t move_down(sokoban_t 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] == '*') {
|
||||
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] = '@';
|
||||
|
@ -148,5 +165,6 @@ sokoban_t move_down(sokoban_t sokoban)
|
|||
sokoban.player_y++;
|
||||
}
|
||||
}
|
||||
|
||||
return (sokoban);
|
||||
}
|
||||
|
|
BIN
src/movement.o
BIN
src/movement.o
Binary file not shown.
43
src/play.c
43
src/play.c
|
@ -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) {
|
||||
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);
|
||||
|
|
BIN
src/play.o
BIN
src/play.o
Binary file not shown.
|
@ -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] == '$')
|
||||
if (sokoban.map[i][j] == '$') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
endwin();
|
||||
exit (0);
|
||||
|
||||
}
|
BIN
src/win_check.o
BIN
src/win_check.o
Binary file not shown.
|
@ -7,14 +7,14 @@
|
|||
** 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_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);
|
||||
|
@ -23,12 +23,9 @@ sokoban_t check_zone_reset(sokoban_t sokoban)
|
|||
return (sokoban);
|
||||
}
|
||||
|
||||
sokoban_t reset_zone(int y, int x, sokoban_t sokoban)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
BIN
src/zone_check.o
BIN
src/zone_check.o
Binary file not shown.
Loading…
Reference in a new issue