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>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#ifndef LIBMY_H
|
#ifndef LIBMY_H
|
||||||
#define LIBMY_H
|
#define LIBMY_H
|
||||||
void my_putchar(char c);
|
void my_putchar(char c);
|
||||||
|
|
|
@ -7,43 +7,72 @@
|
||||||
|
|
||||||
#ifndef BSQ_H
|
#ifndef BSQ_H
|
||||||
#define BSQ_H
|
#define BSQ_H
|
||||||
typedef struct sokoban {
|
|
||||||
char *buffer;
|
typedef struct sokoban {
|
||||||
char **map;
|
char *buffer;
|
||||||
char **map_save;
|
char **map;
|
||||||
int lines;
|
char **map_save;
|
||||||
int player_x;
|
int lines;
|
||||||
int player_y;
|
int player_x;
|
||||||
char const *base_path;
|
int player_y;
|
||||||
int win;
|
char const *base_path;
|
||||||
int case_number;
|
int win;
|
||||||
int num_chars_map;
|
int case_number;
|
||||||
} sokoban_t;
|
int num_chars_map;
|
||||||
int helper(void);
|
} sokoban_t;
|
||||||
char *read_map(int reading);
|
|
||||||
char *open_map(char const *path);
|
int helper(void);
|
||||||
sokoban_t make_map(char const *path, sokoban_t sokoban);
|
|
||||||
int play(char const *path);
|
char *read_map(int reading);
|
||||||
sokoban_t count_lines(sokoban_t sokoban);
|
|
||||||
int count_columns(sokoban_t sokoban, int position);
|
char *open_map(char const *path);
|
||||||
sokoban_t check_if_player(sokoban_t sokoban, int y, int x);
|
|
||||||
sokoban_t find_player(sokoban_t sokoban);
|
sokoban_t make_map(char const *path, sokoban_t sokoban);
|
||||||
sokoban_t key_check(sokoban_t sokoban, int key);
|
|
||||||
sokoban_t move_right(sokoban_t sokoban);
|
int play(char const *path);
|
||||||
sokoban_t move_left(sokoban_t sokoban);
|
|
||||||
sokoban_t move_up(sokoban_t sokoban);
|
sokoban_t count_lines(sokoban_t sokoban);
|
||||||
sokoban_t move_down(sokoban_t sokoban);
|
|
||||||
void win_check(sokoban_t sokoban);
|
int count_columns(sokoban_t sokoban, int position);
|
||||||
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_if_player(sokoban_t sokoban, int y, int x);
|
||||||
sokoban_t check_zone_reset(sokoban_t sokoban);
|
|
||||||
sokoban_t reset_zone(int y, int x, sokoban_t sokoban);
|
sokoban_t find_player(sokoban_t sokoban);
|
||||||
void loose_check(sokoban_t sokoban);
|
|
||||||
void storage_loose_check(int y, int x, sokoban_t sokoban);
|
sokoban_t key_check(sokoban_t sokoban, int key);
|
||||||
void map_check(sokoban_t sokoban);
|
|
||||||
int count_case_number(int y, int x, sokoban_t sokoban);
|
sokoban_t move_right(sokoban_t sokoban);
|
||||||
int count_player(int y, int x, sokoban_t sokoban);
|
|
||||||
sokoban_t game_management(sokoban_t sokoban);
|
sokoban_t move_left(sokoban_t sokoban);
|
||||||
int check_tile(int y, int x, sokoban_t sokoban);
|
|
||||||
int is_goal_cell(int y, int x, 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
|
#endif
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "../include/libmy.h"
|
#include "../include/libmy.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
void my_putchar(char c)
|
void my_putchar(char c) {
|
||||||
{
|
|
||||||
write(1, &c, 1);
|
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"
|
#include "../include/libmy.h"
|
||||||
|
|
||||||
int my_putstr(char const *str)
|
int my_putstr(char const *str) {
|
||||||
{
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (str[i] != '\0') {
|
while (str[i] != '\0') {
|
||||||
my_putchar(str[i]);
|
my_putchar(str[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
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
|
||||||
|
|
237
src/ai/ai.c
237
src/ai/ai.c
|
@ -1,161 +1,166 @@
|
||||||
#include <time.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "ai.h"
|
#include "ai.h"
|
||||||
#include "utils.h"
|
|
||||||
#include "hashtable.h"
|
#include "hashtable.h"
|
||||||
#include "priority_queue.h"
|
#include "priority_queue.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve solution and return a string containing the squence of moves
|
* Retrieve solution and return a string containing the squence of moves
|
||||||
*/
|
*/
|
||||||
char* save_solution( node_t* solution_node ){
|
char *save_solution(node_t *solution_node) {
|
||||||
node_t* n = solution_node;
|
node_t *n = solution_node;
|
||||||
char *solution_string = malloc(sizeof(char) * solution_node->depth+1);
|
char *solution_string = malloc(sizeof(char) * solution_node->depth+1);
|
||||||
solution_string[n->depth] = '\0';
|
solution_string[n->depth] = '\0';
|
||||||
while (n->parent != NULL)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
while (n->parent != NULL) {
|
||||||
switch (n->move) {
|
switch (n->move) {
|
||||||
case up:
|
case up:
|
||||||
if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$')
|
if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$')
|
||||||
solution_string[n->depth-1] = 'U';
|
solution_string[n->depth-1] = 'U';
|
||||||
else
|
else
|
||||||
solution_string[n->depth-1] = 'u';
|
solution_string[n->depth-1] = 'u';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case down:
|
case down:
|
||||||
if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$')
|
if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$')
|
||||||
solution_string[n->depth-1] = 'D';
|
solution_string[n->depth-1] = 'D';
|
||||||
else
|
else
|
||||||
solution_string[n->depth-1] = 'd';
|
solution_string[n->depth-1] = 'd';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case left:
|
case left:
|
||||||
if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$')
|
if (n->parent->state.map[n->state.player_y][n->state.player_x] == '$')
|
||||||
solution_string[n->depth-1] = 'L';
|
solution_string[n->depth-1] = 'L';
|
||||||
else
|
else
|
||||||
solution_string[n->depth-1] = 'l';
|
solution_string[n->depth-1] = 'l';
|
||||||
break;
|
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 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;
|
n = n->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return solution_string;
|
return solution_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy a src into a dst state
|
* 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);
|
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;
|
int width = strlen(src->map[i]) + 1;
|
||||||
dst->map[i] = malloc(width);
|
dst->map[i] = malloc(width);
|
||||||
memcpy(dst->map[i], src->map[i], width);
|
memcpy(dst->map[i], src->map[i], width);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst->player_x = src->player_x;
|
dst->player_x = src->player_x;
|
||||||
dst->player_y = src->player_y;
|
dst->player_y = src->player_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the initial node
|
* Create the initial node
|
||||||
*/
|
*/
|
||||||
node_t* create_init_node( sokoban_t* init_data ){
|
node_t *create_init_node(sokoban_t *init_data) {
|
||||||
node_t * new_n = (node_t *) malloc(sizeof(node_t));
|
node_t *new_n = (node_t *) malloc(sizeof(node_t));
|
||||||
|
|
||||||
new_n->parent = NULL;
|
new_n->parent = NULL;
|
||||||
new_n->priority = 0;
|
new_n->priority = 0;
|
||||||
new_n->depth = 0;
|
new_n->depth = 0;
|
||||||
new_n->num_childs = 0;
|
new_n->num_childs = 0;
|
||||||
new_n->move = -1;
|
new_n->move = -1;
|
||||||
new_n->state.map = malloc(sizeof(char *) * init_data->lines);
|
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;
|
int width = strlen(init_data->map[i]) + 1;
|
||||||
new_n->state.map[i] = malloc(width);
|
new_n->state.map[i] = malloc(width);
|
||||||
memcpy(new_n->state.map[i], init_data->map[i], 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_x = init_data->player_x;
|
||||||
|
|
||||||
new_n->state.player_y = init_data->player_y;
|
new_n->state.player_y = init_data->player_y;
|
||||||
|
|
||||||
return new_n;
|
return new_n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the a node from a parent node
|
* Create the a node from a parent node
|
||||||
*/
|
*/
|
||||||
node_t* create_node( sokoban_t* init_data, node_t* parent ){
|
node_t *create_node(sokoban_t *init_data, node_t *parent) {
|
||||||
node_t * new_n = (node_t *) malloc(sizeof(node_t));
|
node_t *new_n = (node_t *) malloc(sizeof(node_t));
|
||||||
new_n->parent = parent;
|
new_n->parent = parent;
|
||||||
new_n->depth = parent->depth + 1;
|
new_n->depth = parent->depth + 1;
|
||||||
copy_state(init_data, &(new_n->state), &(parent->state));
|
copy_state(init_data, &(new_n->state), &(parent->state));
|
||||||
return new_n;
|
return new_n;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply an action to node n, create a new node resulting from
|
* Apply an action to node n, create a new node resulting from
|
||||||
* executing the action, and return if the player moved
|
* 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;
|
bool player_moved = false;
|
||||||
|
|
||||||
*new_node = create_node( init_data, n );
|
*new_node = create_node(init_data, n);
|
||||||
(*new_node)->move = action;
|
(*new_node)->move = action;
|
||||||
(*new_node)->priority = -(*new_node)->depth;
|
(*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;
|
return player_moved;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Book keeping variable and function to free memory once the solver finishes
|
* Book keeping variable and function to free memory once the solver finishes
|
||||||
*/
|
*/
|
||||||
node_t** expanded_nodes_table;
|
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 );
|
|
||||||
|
|
||||||
|
// 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;
|
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 (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[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(expanded_nodes_table);
|
free(expanded_nodes_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a 2D map, returns a 1D map
|
* 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;
|
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]);
|
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];
|
(*dst_map)[current_i] = src_map[i][j];
|
||||||
current_i++;
|
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
|
* 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
|
// Keep track of solving time
|
||||||
clock_t start = clock();
|
clock_t start = clock();
|
||||||
|
|
||||||
// Solution String containing the sequence of moves
|
// Solution String containing the sequence of moves
|
||||||
char* solution = NULL;
|
char *solution = NULL;
|
||||||
|
|
||||||
HashTable hashTable;
|
HashTable hashTable;
|
||||||
struct heap pq;
|
struct heap pq;
|
||||||
|
@ -185,32 +189,27 @@ void find_solution(sokoban_t* init_data, bool show_solution)
|
||||||
// Choose initial capacity of PRIME NUMBER
|
// Choose initial capacity of PRIME NUMBER
|
||||||
// Specify the size of the keys and values you want to store once
|
// Specify the size of the keys and values you want to store once
|
||||||
// The Hash Table only accept a 1D key and value.
|
// 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
|
// Data structure to create a 1D representation of the map
|
||||||
// Needed to interact with the hash table
|
// 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
|
// Initialize heap
|
||||||
heap_init(&pq);
|
heap_init(&pq);
|
||||||
|
|
||||||
// Initialize expanded nodes table.
|
// Initialize expanded nodes table.
|
||||||
// This table will be used to free your memory once a solution is found
|
// 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
|
// 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
|
// Use the max heap API provided in priority_queue.h
|
||||||
heap_push(&pq,n);
|
heap_push(&pq,n);
|
||||||
|
|
||||||
/**
|
// Implementation of Algorithm 1
|
||||||
* FILL IN THE GRAPH ALGORITHM
|
|
||||||
* */
|
|
||||||
|
|
||||||
while (pq.count > 0) {
|
while (pq.count > 0) {
|
||||||
n = heap_delete(&pq);
|
n = heap_delete(&pq);
|
||||||
update_explore_table(n, expanded_nodes);
|
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);
|
bool player_moved = applyAction(init_data, n, &new, action);
|
||||||
generated_nodes += 1;
|
generated_nodes += 1;
|
||||||
if (!player_moved || simple_corner_deadlock(init_data, &(new->state))) {
|
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->state.map);
|
||||||
free(new);
|
free(new);
|
||||||
continue;
|
continue;
|
||||||
|
@ -235,6 +237,9 @@ void find_solution(sokoban_t* init_data, bool show_solution)
|
||||||
|
|
||||||
if (ht_lookup(&hashTable, flat_map) != NULL) {
|
if (ht_lookup(&hashTable, flat_map) != NULL) {
|
||||||
duplicated_nodes += 1;
|
duplicated_nodes += 1;
|
||||||
|
for (int i = 0; i < init_data->lines; i++) {
|
||||||
|
free(new->state.map[i]);
|
||||||
|
}
|
||||||
free(new->state.map);
|
free(new->state.map);
|
||||||
free(new);
|
free(new);
|
||||||
continue;
|
continue;
|
||||||
|
@ -245,13 +250,13 @@ void find_solution(sokoban_t* init_data, bool show_solution)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------
|
|
||||||
|
|
||||||
// Free Memory of HashTable, Explored and flatmap
|
// Free Memory of HashTable, Explored and flatmap
|
||||||
ht_clear(&hashTable);
|
ht_clear(&hashTable);
|
||||||
ht_destroy(&hashTable);
|
ht_destroy(&hashTable);
|
||||||
free_memory(expanded_nodes);
|
free_memory(expanded_nodes, init_data->lines);
|
||||||
free(flat_map);
|
free(flat_map);
|
||||||
|
|
||||||
|
// Free initial data
|
||||||
for (int i = 0; i < init_data->lines; i++) {
|
for (int i = 0; i < init_data->lines; i++) {
|
||||||
free((init_data->map)[i]);
|
free((init_data->map)[i]);
|
||||||
free((init_data->map_save)[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);
|
||||||
free(init_data->map_save);
|
free(init_data->map_save);
|
||||||
free(init_data->buffer);
|
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
|
// Stop clock
|
||||||
clock_t end = clock();
|
clock_t end = clock();
|
||||||
double cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
|
double cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
|
||||||
|
|
||||||
// Show solution
|
// Show solution
|
||||||
if( show_solution && solution != NULL ) play_solution( *init_data, solution);
|
if (show_solution && solution != NULL) play_solution(*init_data, solution);
|
||||||
|
|
||||||
endwin();
|
endwin();
|
||||||
|
|
||||||
if( solution != NULL ){
|
if (solution != NULL) {
|
||||||
printf("\nSOLUTION: \n");
|
printf("\nSOLUTION: \n");
|
||||||
printf( "%s\n\n", solution);
|
printf("%s\n\n", solution);
|
||||||
|
|
||||||
FILE *fptr = fopen("solution.txt", "w");
|
FILE *fptr = fopen("solution.txt", "w");
|
||||||
if (fptr == NULL)
|
if (fptr == NULL) {
|
||||||
{
|
|
||||||
printf("Could not open file");
|
printf("Could not open file");
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
@ -289,34 +305,25 @@ void find_solution(sokoban_t* init_data, bool show_solution)
|
||||||
free(solution);
|
free(solution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
printf("STATS: \n");
|
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("\tSolution Length: %d\n", solution_size);
|
||||||
printf("\tExpanded/seconds: %d\n", (int)(expanded_nodes/cpu_time_used) );
|
printf("\tExpanded/seconds: %d\n", (int)(expanded_nodes/cpu_time_used));
|
||||||
printf("\tTime (seconds): %f\n", cpu_time_used );
|
printf("\tTime (seconds): %f\n", cpu_time_used);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void solve(char const *path, bool show_solution)
|
void solve(char const *path, bool show_solution) {
|
||||||
{
|
// Load Map
|
||||||
/**
|
|
||||||
* Load Map
|
|
||||||
*/
|
|
||||||
sokoban_t sokoban = make_map(path, sokoban);
|
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;
|
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 <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "priority_queue.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 <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include "hashtable.h"
|
#include "hashtable.h"
|
||||||
|
|
||||||
int ht_setup(HashTable* table,
|
int ht_setup(HashTable* table, size_t key_size, size_t value_size, \
|
||||||
size_t key_size,
|
size_t capacity) {
|
||||||
size_t value_size,
|
|
||||||
size_t capacity) {
|
|
||||||
assert(table != NULL);
|
assert(table != NULL);
|
||||||
|
|
||||||
if (table == NULL) return HT_ERROR;
|
if (table == NULL) {
|
||||||
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (capacity < HT_MINIMUM_CAPACITY) {
|
if (capacity < HT_MINIMUM_CAPACITY) {
|
||||||
capacity = HT_MINIMUM_CAPACITY;
|
capacity = HT_MINIMUM_CAPACITY;
|
||||||
|
@ -38,14 +36,19 @@ int ht_setup(HashTable* table,
|
||||||
}
|
}
|
||||||
|
|
||||||
int ht_copy(HashTable* first, HashTable* second) {
|
int ht_copy(HashTable* first, HashTable* second) {
|
||||||
size_t chain;
|
|
||||||
HTNode* node;
|
|
||||||
|
|
||||||
assert(first != NULL);
|
assert(first != NULL);
|
||||||
assert(ht_is_initialized(second));
|
assert(ht_is_initialized(second));
|
||||||
|
|
||||||
if (first == NULL) return HT_ERROR;
|
size_t chain;
|
||||||
if (!ht_is_initialized(second)) return HT_ERROR;
|
HTNode* node;
|
||||||
|
|
||||||
|
if (first == NULL) {
|
||||||
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ht_is_initialized(second)) {
|
||||||
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (_ht_allocate(first, second->capacity) == HT_ERROR) {
|
if (_ht_allocate(first, second->capacity) == HT_ERROR) {
|
||||||
return HT_ERROR;
|
return HT_ERROR;
|
||||||
|
@ -59,7 +62,9 @@ int ht_copy(HashTable* first, HashTable* second) {
|
||||||
|
|
||||||
for (chain = 0; chain < second->capacity; ++chain) {
|
for (chain = 0; chain < second->capacity; ++chain) {
|
||||||
for (node = second->nodes[chain]; node; node = node->next) {
|
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;
|
return HT_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,8 +77,13 @@ int ht_move(HashTable* first, HashTable* second) {
|
||||||
assert(first != NULL);
|
assert(first != NULL);
|
||||||
assert(ht_is_initialized(second));
|
assert(ht_is_initialized(second));
|
||||||
|
|
||||||
if (first == NULL) return HT_ERROR;
|
if (first == NULL) {
|
||||||
if (!ht_is_initialized(second)) return HT_ERROR;
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ht_is_initialized(second)) {
|
||||||
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
*first = *second;
|
*first = *second;
|
||||||
second->nodes = NULL;
|
second->nodes = NULL;
|
||||||
|
@ -85,8 +95,13 @@ int ht_swap(HashTable* first, HashTable* second) {
|
||||||
assert(ht_is_initialized(first));
|
assert(ht_is_initialized(first));
|
||||||
assert(ht_is_initialized(second));
|
assert(ht_is_initialized(second));
|
||||||
|
|
||||||
if (!ht_is_initialized(first)) return HT_ERROR;
|
if (!ht_is_initialized(first)) {
|
||||||
if (!ht_is_initialized(second)) return HT_ERROR;
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ht_is_initialized(second)) {
|
||||||
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
_ht_int_swap(&first->key_size, &second->key_size);
|
_ht_int_swap(&first->key_size, &second->key_size);
|
||||||
_ht_int_swap(&first->value_size, &second->value_size);
|
_ht_int_swap(&first->value_size, &second->value_size);
|
||||||
|
@ -104,7 +119,9 @@ int ht_destroy(HashTable* table) {
|
||||||
size_t chain;
|
size_t chain;
|
||||||
|
|
||||||
assert(ht_is_initialized(table));
|
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) {
|
for (chain = 0; chain < table->capacity; ++chain) {
|
||||||
node = table->nodes[chain];
|
node = table->nodes[chain];
|
||||||
|
@ -127,8 +144,13 @@ int ht_insert(HashTable* table, void* key, void* value) {
|
||||||
assert(ht_is_initialized(table));
|
assert(ht_is_initialized(table));
|
||||||
assert(key != NULL);
|
assert(key != NULL);
|
||||||
|
|
||||||
if (!ht_is_initialized(table)) return HT_ERROR;
|
if (!ht_is_initialized(table)) {
|
||||||
if (key == NULL) return HT_ERROR;
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == NULL) {
|
||||||
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (_ht_should_grow(table)) {
|
if (_ht_should_grow(table)) {
|
||||||
_ht_adjust_capacity(table);
|
_ht_adjust_capacity(table);
|
||||||
|
@ -158,8 +180,13 @@ int ht_contains(HashTable* table, void* key) {
|
||||||
assert(ht_is_initialized(table));
|
assert(ht_is_initialized(table));
|
||||||
assert(key != NULL);
|
assert(key != NULL);
|
||||||
|
|
||||||
if (!ht_is_initialized(table)) return HT_ERROR;
|
if (!ht_is_initialized(table)) {
|
||||||
if (key == NULL) return HT_ERROR;
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == NULL) {
|
||||||
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
index = _ht_hash(table, key);
|
index = _ht_hash(table, key);
|
||||||
for (node = table->nodes[index]; node; node = node->next) {
|
for (node = table->nodes[index]; node; node = node->next) {
|
||||||
|
@ -178,8 +205,13 @@ void* ht_lookup(HashTable* table, void* key) {
|
||||||
assert(table != NULL);
|
assert(table != NULL);
|
||||||
assert(key != NULL);
|
assert(key != NULL);
|
||||||
|
|
||||||
if (table == NULL) return NULL;
|
if (table == NULL) {
|
||||||
if (key == NULL) return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
index = _ht_hash(table, key);
|
index = _ht_hash(table, key);
|
||||||
for (node = table->nodes[index]; node; node = node->next) {
|
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(table != NULL);
|
||||||
assert(key != NULL);
|
assert(key != NULL);
|
||||||
|
|
||||||
if (table == NULL) return NULL;
|
if (table == NULL) {
|
||||||
if (key == NULL) return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
index = _ht_hash(table, key);
|
index = _ht_hash(table, key);
|
||||||
for (node = table->nodes[index]; node; node = node->next) {
|
for (node = table->nodes[index]; node; node = node->next) {
|
||||||
|
@ -219,8 +256,13 @@ int ht_erase(HashTable* table, void* key) {
|
||||||
assert(table != NULL);
|
assert(table != NULL);
|
||||||
assert(key != NULL);
|
assert(key != NULL);
|
||||||
|
|
||||||
if (table == NULL) return HT_ERROR;
|
if (table == NULL) {
|
||||||
if (key == NULL) return HT_ERROR;
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == NULL) {
|
||||||
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
index = _ht_hash(table, key);
|
index = _ht_hash(table, key);
|
||||||
node = table->nodes[index];
|
node = table->nodes[index];
|
||||||
|
@ -253,8 +295,13 @@ int ht_clear(HashTable* table) {
|
||||||
assert(table != NULL);
|
assert(table != NULL);
|
||||||
assert(table->nodes != NULL);
|
assert(table->nodes != NULL);
|
||||||
|
|
||||||
if (table == NULL) return HT_ERROR;
|
if (table == NULL) {
|
||||||
if (table->nodes == NULL) return HT_ERROR;
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (table->nodes == NULL) {
|
||||||
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ht_destroy(table);
|
ht_destroy(table);
|
||||||
_ht_allocate(table, HT_MINIMUM_CAPACITY);
|
_ht_allocate(table, HT_MINIMUM_CAPACITY);
|
||||||
|
@ -265,7 +312,11 @@ int ht_clear(HashTable* table) {
|
||||||
|
|
||||||
int ht_is_empty(HashTable* table) {
|
int ht_is_empty(HashTable* table) {
|
||||||
assert(table != NULL);
|
assert(table != NULL);
|
||||||
if (table == NULL) return HT_ERROR;
|
|
||||||
|
if (table == NULL) {
|
||||||
|
return HT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
return table->size == 0;
|
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;
|
if (!ht_is_initialized(table)) return HT_ERROR;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We expect the "minimum capacity" to be in elements, not in array indices.
|
* We expect the "minimum capacity" to be in elements,
|
||||||
* This encapsulates the design.
|
* not in array indices. This encapsulates the design.
|
||||||
*/
|
*/
|
||||||
if (minimum_capacity > table->threshold) {
|
if (minimum_capacity > table->threshold) {
|
||||||
return _ht_resize(table, minimum_capacity / HT_LOAD_FACTOR);
|
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) {
|
if ((node = malloc(sizeof *node)) == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((node->key = malloc(table->key_size)) == NULL) {
|
if ((node->key = malloc(table->key_size)) == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((node->value = malloc(table->value_size)) == NULL) {
|
if ((node->value = malloc(table->value_size)) == NULL) {
|
||||||
return 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) {
|
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;
|
return table->nodes[index] == NULL ? HT_ERROR : HT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,23 +13,19 @@
|
||||||
#define HT_MINIMUM_CAPACITY 8
|
#define HT_MINIMUM_CAPACITY 8
|
||||||
#define HT_LOAD_FACTOR 5
|
#define HT_LOAD_FACTOR 5
|
||||||
#define HT_MINIMUM_THRESHOLD (HT_MINIMUM_CAPACITY) * (HT_LOAD_FACTOR)
|
#define HT_MINIMUM_THRESHOLD (HT_MINIMUM_CAPACITY) * (HT_LOAD_FACTOR)
|
||||||
|
|
||||||
#define HT_GROWTH_FACTOR 2
|
#define HT_GROWTH_FACTOR 2
|
||||||
#define HT_SHRINK_THRESHOLD (1 / 4)
|
#define HT_SHRINK_THRESHOLD (1 / 4)
|
||||||
|
|
||||||
#define HT_ERROR -1
|
#define HT_ERROR -1
|
||||||
#define HT_SUCCESS 0
|
#define HT_SUCCESS 0
|
||||||
|
|
||||||
#define HT_UPDATED 1
|
#define HT_UPDATED 1
|
||||||
#define HT_INSERTED 0
|
#define HT_INSERTED 0
|
||||||
|
|
||||||
#define HT_NOT_FOUND 0
|
#define HT_NOT_FOUND 0
|
||||||
#define HT_FOUND 01
|
#define HT_FOUND 01
|
||||||
|
|
||||||
#define HT_INITIALIZER {0, 0, 0, 0, 0, NULL, NULL, NULL};
|
#define HT_INITIALIZER {0, 0, 0, 0, 0, NULL, NULL, NULL};
|
||||||
|
|
||||||
typedef int (*comparison_t)(void*, void*, size_t);
|
typedef int (*comparison_t)(void *, void *, size_t);
|
||||||
typedef size_t (*hash_t)(void*, size_t);
|
|
||||||
|
typedef size_t (*hash_t)(void *, size_t);
|
||||||
|
|
||||||
/****************** STRUCTURES ******************/
|
/****************** STRUCTURES ******************/
|
||||||
|
|
||||||
|
@ -58,13 +54,13 @@ typedef struct HashTable {
|
||||||
/****************** INTERFACE ******************/
|
/****************** INTERFACE ******************/
|
||||||
|
|
||||||
/* Setup */
|
/* Setup */
|
||||||
int ht_setup(HashTable* table,
|
int ht_setup(HashTable* table, size_t key_size, size_t value_size, \
|
||||||
size_t key_size,
|
size_t capacity);
|
||||||
size_t value_size,
|
|
||||||
size_t capacity);
|
|
||||||
|
|
||||||
int ht_copy(HashTable* first, HashTable* second);
|
int ht_copy(HashTable* first, HashTable* second);
|
||||||
|
|
||||||
int ht_move(HashTable* first, HashTable* second);
|
int ht_move(HashTable* first, HashTable* second);
|
||||||
|
|
||||||
int ht_swap(HashTable* first, HashTable* second);
|
int ht_swap(HashTable* first, HashTable* second);
|
||||||
|
|
||||||
/* Destructor */
|
/* Destructor */
|
||||||
|
@ -73,16 +69,20 @@ int ht_destroy(HashTable* table);
|
||||||
int ht_insert(HashTable* table, void* key, void* value);
|
int ht_insert(HashTable* table, void* key, void* value);
|
||||||
|
|
||||||
int ht_contains(HashTable* table, void* key);
|
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) \
|
#define HT_LOOKUP_AS(type, table_pointer, key_pointer) \
|
||||||
(*(type*)ht_lookup((table_pointer), (key_pointer)))
|
(*(type*)ht_lookup((table_pointer), (key_pointer)))
|
||||||
|
|
||||||
int ht_erase(HashTable* table, void* key);
|
int ht_erase(HashTable* table, void* key);
|
||||||
|
|
||||||
int ht_clear(HashTable* table);
|
int ht_clear(HashTable* table);
|
||||||
|
|
||||||
int ht_is_empty(HashTable* table);
|
int ht_is_empty(HashTable* table);
|
||||||
|
|
||||||
bool ht_is_initialized(HashTable* table);
|
bool ht_is_initialized(HashTable* table);
|
||||||
|
|
||||||
int ht_reserve(HashTable* table, size_t minimum_capacity);
|
int ht_reserve(HashTable* table, size_t minimum_capacity);
|
||||||
|
@ -90,24 +90,34 @@ int ht_reserve(HashTable* table, size_t minimum_capacity);
|
||||||
/****************** PRIVATE ******************/
|
/****************** PRIVATE ******************/
|
||||||
|
|
||||||
void _ht_int_swap(size_t* first, size_t* second);
|
void _ht_int_swap(size_t* first, size_t* second);
|
||||||
|
|
||||||
void _ht_pointer_swap(void** first, void** second);
|
void _ht_pointer_swap(void** first, void** second);
|
||||||
|
|
||||||
size_t _ht_default_hash(void* key, size_t key_size);
|
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);
|
int _ht_default_compare(void* first_key, void* second_key, size_t key_size);
|
||||||
|
|
||||||
size_t _ht_hash(const HashTable* table, void* key);
|
size_t _ht_hash(const HashTable* table, void* key);
|
||||||
|
|
||||||
bool _ht_equal(const HashTable* table, void* first_key, void* second_key);
|
bool _ht_equal(const HashTable* table, void* first_key, void* second_key);
|
||||||
|
|
||||||
bool _ht_should_grow(HashTable* table);
|
bool _ht_should_grow(HashTable* table);
|
||||||
|
|
||||||
bool _ht_should_shrink(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);
|
int _ht_push_front(HashTable* table, size_t index, void* key, void* value);
|
||||||
|
|
||||||
void _ht_destroy_node(HTNode* node);
|
void _ht_destroy_node(HTNode* node);
|
||||||
|
|
||||||
int _ht_adjust_capacity(HashTable* table);
|
int _ht_adjust_capacity(HashTable* table);
|
||||||
|
|
||||||
int _ht_allocate(HashTable* table, size_t capacity);
|
int _ht_allocate(HashTable* table, size_t capacity);
|
||||||
|
|
||||||
int _ht_resize(HashTable* table, size_t new_capacity);
|
int _ht_resize(HashTable* table, size_t new_capacity);
|
||||||
|
|
||||||
void _ht_rehash(HashTable* table, HTNode** old, size_t old_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"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data structure containing the node information
|
* Data structure containing the node information
|
||||||
*/
|
*/
|
||||||
struct node_s{
|
typedef struct node_s {
|
||||||
int priority;
|
int priority;
|
||||||
int depth;
|
int depth;
|
||||||
int num_childs;
|
int num_childs;
|
||||||
move_t move;
|
move_t move;
|
||||||
state_t state;
|
state_t state;
|
||||||
struct node_s* parent;
|
struct node_s* parent;
|
||||||
};
|
} node_t;
|
||||||
|
|
||||||
typedef struct node_s node_t;
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,109 +2,115 @@
|
||||||
|
|
||||||
int *heap, size, count;
|
int *heap, size, count;
|
||||||
|
|
||||||
void heap_init(struct heap* h)
|
void heap_init(struct heap *h) {
|
||||||
{
|
|
||||||
h->count = 0;
|
h->count = 0;
|
||||||
h->size = initial_size;
|
h->size = initial_size;
|
||||||
h->heaparr = (node_t **) malloc(sizeof(node_t*) * initial_size);
|
h->heaparr = (node_t **) malloc(sizeof(node_t*) * initial_size);
|
||||||
for(int i = 0; i < initial_size; i++)
|
|
||||||
h->heaparr[i]=NULL;
|
|
||||||
|
|
||||||
if(!h->heaparr) {
|
for (int i = 0; i < initial_size; i++) {
|
||||||
|
h->heaparr[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!h->heaparr) {
|
||||||
printf("Error allocatinga memory...\n");
|
printf("Error allocatinga memory...\n");
|
||||||
exit(-1);
|
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;
|
int left, right, largest;
|
||||||
node_t* temp;
|
node_t *temp;
|
||||||
left = 2*(loc) + 1;
|
left = 2 * (loc) + 1;
|
||||||
right = left + 1;
|
right = left + 1;
|
||||||
largest = loc;
|
largest = loc;
|
||||||
|
|
||||||
|
|
||||||
if (left <= count && data[left]->priority > data[largest]->priority) {
|
if (left <= count && data[left]->priority > data[largest]->priority) {
|
||||||
largest = left;
|
largest = left;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (right <= count && data[right]->priority > data[largest]->priority) {
|
if (right <= count && data[right]->priority > data[largest]->priority) {
|
||||||
largest = right;
|
largest = right;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(largest != loc) {
|
if (largest != loc) {
|
||||||
temp = data[loc];
|
temp = data[loc];
|
||||||
data[loc] = data[largest];
|
data[loc] = data[largest];
|
||||||
data[largest] = temp;
|
data[largest] = temp;
|
||||||
max_heapify(data, largest, count);
|
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;
|
int index, parent;
|
||||||
|
|
||||||
// Resize the heap if it is too small to hold all the data
|
// 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->size += 1;
|
||||||
h->heaparr = realloc(h->heaparr, sizeof(node_t) * h->size);
|
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
|
// Find out where to put the element and put it
|
||||||
for(;index; index = parent)
|
for (; index; index = parent) {
|
||||||
{
|
|
||||||
parent = (index - 1) / 2;
|
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] = h->heaparr[parent];
|
||||||
}
|
}
|
||||||
|
|
||||||
h->heaparr[index] = value;
|
h->heaparr[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void heap_display(struct heap* h, sokoban_t* init_data) {
|
void heap_display(struct heap *h, sokoban_t *init_data) {
|
||||||
int i;
|
for (int i = 0; i < h->count; ++i) {
|
||||||
for(i=0; i<h->count; ++i) {
|
node_t *n = h->heaparr[i];
|
||||||
node_t* n = h->heaparr[i];
|
|
||||||
|
printf("priority = %d\n", n->priority);
|
||||||
|
|
||||||
|
for (int j = 0; i < init_data->lines; j++) {
|
||||||
|
mvprintw(i, 0, n->state.map[j]);
|
||||||
|
}
|
||||||
|
|
||||||
printf("priority = %d", n->priority);
|
|
||||||
printf("\n");
|
|
||||||
for (int i = 0; i < init_data->lines; i++)
|
|
||||||
mvprintw(i, 0, n->state.map[i]);
|
|
||||||
move(n->state.player_y, n->state.player_x);
|
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* removed;
|
node_t *temp = h->heaparr[--h->count];
|
||||||
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->size -= 1;
|
||||||
h->heaparr = realloc(h->heaparr, sizeof(node_t) * h->size);
|
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];
|
removed = h->heaparr[0];
|
||||||
h->heaparr[0] = temp;
|
h->heaparr[0] = temp;
|
||||||
if(temp == removed) h->heaparr[0] = NULL;
|
if (temp == removed) {
|
||||||
max_heapify(h->heaparr, 0, h->count);
|
h->heaparr[0] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_heapify(h->heaparr, 0, h->count);
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void emptyPQ(struct heap* pq) {
|
void emptyPQ(struct heap *pq) {
|
||||||
while(pq->count != 0) {
|
while(pq->count != 0) {
|
||||||
node_t* n = heap_delete(pq);
|
node_t *n = heap_delete(pq);
|
||||||
for (int i = size; i >= 0; i--) {
|
|
||||||
free(n->state.map[i]);
|
|
||||||
}
|
|
||||||
free(n->state.map);
|
|
||||||
free(n);
|
free(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,19 @@
|
||||||
#define __PQ__
|
#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 <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <curses.h>
|
#include <curses.h>
|
||||||
|
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "../../include/sokoban.h"
|
#include "../../include/sokoban.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* size is the allocated size, count is the number of elements in the queue
|
* size is the allocated size, count is the number of elements in the queue
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct heap {
|
struct heap {
|
||||||
int size;
|
int size;
|
||||||
int count;
|
int count;
|
||||||
|
@ -24,16 +23,16 @@ struct heap {
|
||||||
|
|
||||||
#define initial_size 4
|
#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);
|
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
|
#endif
|
||||||
|
|
Binary file not shown.
269
src/ai/utils.c
269
src/ai/utils.c
|
@ -1,256 +1,316 @@
|
||||||
#include <curses.h>
|
#include <curses.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
/*********
|
||||||
|
* MACROS *
|
||||||
|
*********/
|
||||||
|
|
||||||
|
#define TERMINAL_TYPE (strcmp(getenv("TERM"), "xterm") == 0 ? "rxvt" : \
|
||||||
|
getenv("TERM"))
|
||||||
|
|
||||||
/**************************************
|
/**************************************
|
||||||
* Box movement given a state state *
|
* Box movement given a state state *
|
||||||
***************************************/
|
***************************************/
|
||||||
|
|
||||||
bool is_goal_loc(int y, int x, sokoban_t* init_data)
|
bool is_goal_loc(int y, int x, sokoban_t *init_data) {
|
||||||
{
|
return (init_data->map_save[y][x] == '.') || \
|
||||||
return (init_data->map_save[y][x] == '.') || (init_data->map_save[y][x] == '+') || (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;
|
return false;
|
||||||
} else if (state->map[state->player_y][state->player_x-2] == '#') {
|
} else if (state->map[state->player_y][state->player_x-2] == '#') {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
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-2] == '.')
|
|
||||||
|
if (state->map[state->player_y][state->player_x-2] == '.') {
|
||||||
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-2] = '$';
|
||||||
|
}
|
||||||
|
|
||||||
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] == ' ') {
|
|
||||||
|
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->map[state->player_y][state->player_x] = '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
state->player_x--;
|
state->player_x--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool push_box_right(sokoban_t* init_data,state_t* state)
|
bool push_box_right(sokoban_t *init_data, state_t *state) {
|
||||||
{
|
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] == '*') {
|
state->map[state->player_y][state->player_x+2] == '*') {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} else if (state->map[state->player_y][state->player_x+2] == '#') {
|
} else if (state->map[state->player_y][state->player_x+2] == '#') {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
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+2] == '.')
|
|
||||||
|
if (state->map[state->player_y][state->player_x+2] == '.') {
|
||||||
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+2] = '$';
|
||||||
|
}
|
||||||
|
|
||||||
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] = '.';
|
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++;
|
state->player_x++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool push_box_up(sokoban_t* init_data,state_t* state)
|
bool push_box_up(sokoban_t *init_data, state_t *state) {
|
||||||
{
|
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] == '*') {
|
state->map[state->player_y-2][state->player_x] == '*') {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} else if (state->map[state->player_y-2][state->player_x] == '#') {
|
} else if (state->map[state->player_y-2][state->player_x] == '#') {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
state->map[state->player_y-1][state->player_x] = '@';
|
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] = '*';
|
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-2][state->player_x] = '$';
|
||||||
|
}
|
||||||
|
|
||||||
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] = '.';
|
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--;
|
state->player_y--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool push_box_down(sokoban_t* init_data,state_t* state)
|
bool push_box_down(sokoban_t *init_data, state_t *state) {
|
||||||
{
|
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] == '*') {
|
state->map[state->player_y+2][state->player_x] == '*') {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} else if (state->map[state->player_y+2][state->player_x] == '#') {
|
} else if (state->map[state->player_y+2][state->player_x] == '#') {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
state->map[state->player_y+1][state->player_x] = '@';
|
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] = '*';
|
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+2][state->player_x] = '$';
|
||||||
|
}
|
||||||
|
|
||||||
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] = '.';
|
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++;
|
state->player_y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************
|
/**************************************
|
||||||
* Player Moves given a state state *
|
* 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] != '#') {
|
||||||
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);
|
return push_box_left(init_data, state);
|
||||||
} else {
|
} else {
|
||||||
state->map[state->player_y][state->player_x-1] = '@';
|
state->map[state->player_y][state->player_x-1] = '@';
|
||||||
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] == ' ') {
|
|
||||||
|
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->map[state->player_y][state->player_x] = '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
state->player_x--;
|
state->player_x--;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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] != '#') {
|
||||||
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);
|
return push_box_right(init_data, state);
|
||||||
} else {
|
} else {
|
||||||
state->map[state->player_y][state->player_x+1] = '@';
|
state->map[state->player_y][state->player_x+1] = '@';
|
||||||
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] == ' ') {
|
|
||||||
|
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->map[state->player_y][state->player_x] = '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
state->player_x++;
|
state->player_x++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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] != '#') {
|
||||||
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);
|
return push_box_up(init_data, state);
|
||||||
} else {
|
} else {
|
||||||
state->map[state->player_y-1][state->player_x] = '@';
|
state->map[state->player_y-1][state->player_x] = '@';
|
||||||
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] == ' ') {
|
|
||||||
|
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->map[state->player_y][state->player_x] = '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
state->player_y--;
|
state->player_y--;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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] != '#') {
|
||||||
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);
|
return push_box_down(init_data, state);
|
||||||
} else {
|
} else {
|
||||||
state->map[state->player_y+1][state->player_x] = '@';
|
state->map[state->player_y+1][state->player_x] = '@';
|
||||||
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] == ' ') {
|
|
||||||
|
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->map[state->player_y][state->player_x] = '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
state->player_y++;
|
state->player_y++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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;
|
bool player_moved = false;
|
||||||
|
|
||||||
//Determine which button is pushed
|
// Determine which button is pushed
|
||||||
switch (move) {
|
switch (move) {
|
||||||
case up:
|
case up:
|
||||||
player_moved = move_up_player(init_data, state);
|
player_moved = move_up_player(init_data, state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case down:
|
case down:
|
||||||
player_moved = move_down_player(init_data, state);
|
player_moved = move_down_player(init_data, state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case left:
|
case left:
|
||||||
player_moved = move_left_player(init_data, state);
|
player_moved = move_left_player(init_data, state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case right:
|
|
||||||
player_moved = move_right_player(init_data, state);
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
case right:
|
||||||
|
player_moved = move_right_player(init_data, state);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return player_moved;
|
return player_moved;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Function: simple_corner_deadlock *
|
* Function: simple_corner_deadlock *
|
||||||
* Parameters: sokoban_t* init_data, state_t* state *
|
* Parameters: sokoban_t *init_data, state_t *state *
|
||||||
* Returns: bool *
|
* Returns: bool *
|
||||||
* Description: Check if box has been pusehd into a loc in a corner wall *
|
* Description: Check if box has been pusehd into a loc in a corner wall *
|
||||||
* and loc != destination *
|
* 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
|
// Check if corner
|
||||||
if (((state->map[y][x+1] == '#' && state->map[y+1][x] == '#') ||
|
if (((state->map[y][x+1] == '#' && state->map[y+1][x] == '#') ||
|
||||||
(state->map[y+1][x] == '#' && state->map[y][x-1] == '#') ||
|
(state->map[y+1][x] == '#' && state->map[y][x-1] == '#') ||
|
||||||
(state->map[y][x-1] == '#' && state->map[y-1][x] == '#') ||
|
(state->map[y][x-1] == '#' && state->map[y-1][x] == '#') ||
|
||||||
(state->map[y-1][x] == '#' && state->map[y][x+1] == '#')) &&
|
(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 true;
|
||||||
}
|
}
|
||||||
return false;
|
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;
|
bool deadlock = false;
|
||||||
int x = state->player_x;
|
int x = state->player_x;
|
||||||
int y = state->player_y;
|
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;
|
y = state->player_y + 1;
|
||||||
deadlock = corner_check(x, y, init_data, state);
|
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;
|
y = state->player_y - 1;
|
||||||
deadlock = corner_check(x, y, init_data, state);
|
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;
|
x = state->player_x + 1;
|
||||||
deadlock = corner_check(x, y, init_data, state);
|
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;
|
x = state->player_x - 1;
|
||||||
deadlock = corner_check(x, y, init_data, state);
|
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;
|
return deadlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Function: winning_condition *
|
* Function: winning_condition *
|
||||||
* Parameters: sokoban_t* init_data, state_t* state *
|
* Parameters: sokoban_t *init_data, state_t *state *
|
||||||
* Returns: bool *
|
* Returns: bool *
|
||||||
* Description: Check if all boxes are in a destination *
|
* 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 y = 0; y < init_data->lines; y++) {
|
||||||
for (int x = 0; init_data->map_save[y][x] != '\0'; x++) {
|
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 false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********
|
void play_solution(sokoban_t init_data, char *solution) {
|
||||||
* 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);
|
SCREEN *mainScreen = newterm(TERMINAL_TYPE, stdout, stdin);
|
||||||
set_term(mainScreen);
|
set_term(mainScreen);
|
||||||
int cols = 1;
|
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]);
|
cols = strlen(init_data.map[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WINDOW *mainWindow = newwin(init_data.lines, cols, 0, 0);
|
WINDOW *mainWindow = newwin(init_data.lines, cols, 0, 0);
|
||||||
|
|
||||||
cbreak();
|
cbreak();
|
||||||
|
@ -310,24 +360,29 @@ void play_solution( sokoban_t init_data, char* solution ){
|
||||||
wnoutrefresh(mainWindow);
|
wnoutrefresh(mainWindow);
|
||||||
doupdate();
|
doupdate();
|
||||||
refresh();
|
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]);
|
mvprintw(i, 0, init_data.map[i]);
|
||||||
|
}
|
||||||
move(init_data.player_y, init_data.player_x);
|
move(init_data.player_y, init_data.player_x);
|
||||||
|
|
||||||
int key_pressed = 0;
|
int key_pressed = 0;
|
||||||
|
|
||||||
if( solution[i] == 'u' || solution[i] == 'U')
|
if (solution[i] == 'u' || solution[i] == 'U') {
|
||||||
key_pressed = KEY_UP;
|
key_pressed = KEY_UP;
|
||||||
else if( solution[i] == 'd' || solution[i] == 'D')
|
} else if (solution[i] == 'd' || solution[i] == 'D') {
|
||||||
key_pressed = KEY_DOWN;
|
key_pressed = KEY_DOWN;
|
||||||
else if( solution[i] == 'l' || solution[i] == 'L')
|
} else if (solution[i] == 'l' || solution[i] == 'L') {
|
||||||
key_pressed = KEY_LEFT;
|
key_pressed = KEY_LEFT;
|
||||||
else if( solution[i] == 'r' || solution[i] == 'R')
|
} else if (solution[i] == 'r' || solution[i] == 'R') {
|
||||||
key_pressed = KEY_RIGHT;
|
key_pressed = KEY_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
init_data = key_check(init_data, key_pressed);
|
init_data = key_check(init_data, key_pressed);
|
||||||
init_data = check_zone_reset(init_data);
|
init_data = check_zone_reset(init_data);
|
||||||
usleep(500000);
|
usleep(500000);
|
||||||
}
|
}
|
||||||
|
|
||||||
touchwin(mainWindow);
|
touchwin(mainWindow);
|
||||||
wnoutrefresh(mainWindow);
|
wnoutrefresh(mainWindow);
|
||||||
doupdate();
|
doupdate();
|
||||||
|
@ -335,12 +390,12 @@ void play_solution( sokoban_t init_data, char* solution ){
|
||||||
usleep(1500000);
|
usleep(1500000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_map(sokoban_t* init_data, state_t* state ){
|
void print_map(sokoban_t *init_data, state_t *state) {
|
||||||
initscr();
|
initscr();
|
||||||
cbreak();
|
cbreak();
|
||||||
noecho();
|
noecho();
|
||||||
clear();
|
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]);
|
mvprintw(i, 0, state->map[i]);
|
||||||
move(state->player_y, state->player_x);
|
move(state->player_y, state->player_x);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
#ifndef __UTILS__
|
#ifndef __UTILS__
|
||||||
#define __UTILS__
|
#define __UTILS__
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <signal.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../../include/sokoban.h"
|
#include "../../include/sokoban.h"
|
||||||
|
|
||||||
#define SIZE 4
|
#define SIZE 4
|
||||||
|
@ -19,14 +20,11 @@
|
||||||
* Data structure containing the information about the game state
|
* Data structure containing the information about the game state
|
||||||
* representing the state of the game.
|
* representing the state of the game.
|
||||||
*/
|
*/
|
||||||
struct state_s{
|
typedef struct state_s{
|
||||||
char **map;
|
char **map;
|
||||||
int player_x;
|
int player_x;
|
||||||
int player_y;
|
int player_y;
|
||||||
};
|
} state_t;
|
||||||
|
|
||||||
typedef struct state_s state_t;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move type
|
* Move type
|
||||||
|
@ -38,15 +36,18 @@ typedef enum moves{
|
||||||
down=3
|
down=3
|
||||||
} move_t;
|
} move_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper functions
|
* Helper functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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 simple_corner_deadlock(sokoban_t *init_data, state_t *state);
|
bool simple_corner_deadlock(sokoban_t *init_data, state_t *state);
|
||||||
|
|
||||||
bool winning_condition(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);
|
void print_map(sokoban_t *init_data, state_t *state);
|
||||||
|
|
||||||
#endif
|
#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
|
** Function for finding the player on the map
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ncurses.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../include/libmy.h"
|
#include "../include/libmy.h"
|
||||||
#include "../include/sokoban.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_x = 0;
|
||||||
sokoban.player_y = 0;
|
sokoban.player_y = 0;
|
||||||
|
|
||||||
for (int i = 0; i < sokoban.lines; i++) {
|
for (int i = 0; i < sokoban.lines; i++) {
|
||||||
for (int j = 0; sokoban.map[i][j] != '\0'; j++) {
|
for (int j = 0; sokoban.map[i][j] != '\0'; j++) {
|
||||||
sokoban = check_if_player(sokoban, i, j);
|
sokoban = check_if_player(sokoban, i, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sokoban);
|
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] == '@') {
|
if (sokoban.map[y][x] == '@') {
|
||||||
sokoban.player_x = x;
|
sokoban.player_x = x;
|
||||||
sokoban.player_y = y;
|
sokoban.player_y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sokoban);
|
return (sokoban);
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -2,14 +2,14 @@
|
||||||
** EPITECH PROJECT, 2017
|
** EPITECH PROJECT, 2017
|
||||||
** PSU_my_sokoban_2017
|
** PSU_my_sokoban_2017
|
||||||
** File description:
|
** File description:
|
||||||
** Main function for the my_sokoban
|
** Function for printing CLI usage
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../include/libmy.h"
|
#include "../include/libmy.h"
|
||||||
|
|
||||||
int helper(void)
|
int helper(void) {
|
||||||
{
|
|
||||||
my_putstr("USAGE\n");
|
my_putstr("USAGE\n");
|
||||||
my_putstr(" ./sokoban <-s> map <play_solution>\n\n");
|
my_putstr(" ./sokoban <-s> map <play_solution>\n\n");
|
||||||
my_putstr("DESCRIPTION\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
|
** Function that manage key press for sokoban
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ncurses.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../include/libmy.h"
|
#include "../include/libmy.h"
|
||||||
#include "../include/sokoban.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) {
|
if (key == KEY_LEFT) {
|
||||||
sokoban = move_left(sokoban);
|
sokoban = move_left(sokoban);
|
||||||
}
|
}
|
||||||
if (key == KEY_RIGHT)
|
|
||||||
|
if (key == KEY_RIGHT) {
|
||||||
sokoban = move_right(sokoban);
|
sokoban = move_right(sokoban);
|
||||||
if (key == KEY_UP)
|
}
|
||||||
|
|
||||||
|
if (key == KEY_UP) {
|
||||||
sokoban = move_up(sokoban);
|
sokoban = move_up(sokoban);
|
||||||
if (key == KEY_DOWN)
|
}
|
||||||
|
|
||||||
|
if (key == KEY_DOWN) {
|
||||||
sokoban = move_down(sokoban);
|
sokoban = move_down(sokoban);
|
||||||
if (key == ' ')
|
}
|
||||||
|
|
||||||
|
if (key == ' ') {
|
||||||
play(sokoban.base_path);
|
play(sokoban.base_path);
|
||||||
|
}
|
||||||
|
|
||||||
return (sokoban);
|
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
|
** Functions used to check if the game is loosed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ncurses.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../include/libmy.h"
|
#include "../include/libmy.h"
|
||||||
#include "../include/sokoban.h"
|
#include "../include/sokoban.h"
|
||||||
|
|
||||||
void loose_check(sokoban_t sokoban)
|
void loose_check(sokoban_t sokoban) {
|
||||||
{
|
if (sokoban.map[sokoban.player_y + 1][sokoban.player_x] == '$') {
|
||||||
if( sokoban.map[sokoban.player_y+1][sokoban.player_x] == '$')
|
storage_loose_check(sokoban.player_y + 1, sokoban.player_x, sokoban);
|
||||||
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);
|
|
||||||
|
|
||||||
|
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] == '$') {
|
||||||
if (((sokoban.map[y][x+1] == '#' && sokoban.map[y+1][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+1][x] == '#' && sokoban.map[y][x-1] == '#') ||
|
||||||
(sokoban.map[y][x-1] == '#' && sokoban.map[y-1][x] == '#') ||
|
(sokoban.map[y][x-1] == '#' && sokoban.map[y-1][x] == '#') ||
|
||||||
(sokoban.map[y-1][x] == '#' && sokoban.map[y][x+1] == '#')) &&
|
(sokoban.map[y-1][x] == '#' && sokoban.map[y][x+1] == '#')) &&
|
||||||
!is_goal_cell(y, x, sokoban ) ) {
|
!is_goal_cell(y, x, sokoban ) ) {
|
||||||
|
|
||||||
endwin();
|
endwin();
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
23
src/main.c
23
src/main.c
|
@ -5,29 +5,32 @@
|
||||||
** Main function for the my_sokoban
|
** Main function for the my_sokoban
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ncurses.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <ncurses.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../include/libmy.h"
|
#include "../include/libmy.h"
|
||||||
#include "../include/sokoban.h"
|
#include "../include/sokoban.h"
|
||||||
#include "ai/ai.h"
|
#include "ai/ai.h"
|
||||||
|
|
||||||
int main(int argc, char const **argv)
|
int main(int argc, char const **argv) {
|
||||||
{
|
if (argc < 2 || argc > 4) {
|
||||||
if (argc < 2 || argc > 4)
|
|
||||||
return (84);
|
return (84);
|
||||||
if (argv[1][0] == '-' && argv[1][1] == 'h')
|
}
|
||||||
|
|
||||||
|
if (argv[1][0] == '-' && argv[1][1] == 'h') {
|
||||||
return(helper());
|
return(helper());
|
||||||
else if (argv[1][0] == '-' && argv[1][1] == 's'){
|
} else if (argv[1][0] == '-' && argv[1][1] == 's') {
|
||||||
bool show_solution = false;
|
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;
|
show_solution = true;
|
||||||
|
}
|
||||||
solve(argv[2], show_solution);
|
solve(argv[2], show_solution);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else if (argv[1][0] != '-') {
|
||||||
else if (argv[1][0] != '-')
|
|
||||||
return(play(argv[1]));
|
return(play(argv[1]));
|
||||||
|
}
|
||||||
|
|
||||||
return (84);
|
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
|
** Function used to check if a map is valid or not
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../include/libmy.h"
|
#include "../include/libmy.h"
|
||||||
#include "../include/sokoban.h"
|
#include "../include/sokoban.h"
|
||||||
|
|
||||||
void map_check(sokoban_t sokoban)
|
void map_check(sokoban_t sokoban) {
|
||||||
{
|
|
||||||
|
|
||||||
int player = 0;
|
int player = 0;
|
||||||
|
|
||||||
for (int i = 0; i < sokoban.lines; i++) {
|
for (int i = 0; i < sokoban.lines; i++) {
|
||||||
for (int j = 0; sokoban.map_save[i][j] != '\0'; j++) {
|
for (int j = 0; sokoban.map_save[i][j] != '\0'; j++) {
|
||||||
|
|
||||||
check_tile(i, j, sokoban);
|
check_tile(i, j, sokoban);
|
||||||
player += count_player(i, j, sokoban);
|
player += count_player(i, j, sokoban);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_tile(int y, int x, sokoban_t sokoban)
|
int check_tile(int y, int x, sokoban_t sokoban) {
|
||||||
{
|
if (sokoban.map_save[y][x] != '@' && sokoban.map_save[y][x] != '$' && \
|
||||||
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] != '#' && sokoban.map_save[y][x] != ' '
|
sokoban.map_save[y][x] != '\n' && 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] != '*') {
|
||||||
&& sokoban.map_save[y][x] != '+' && sokoban.map_save[y][x] != '*')
|
|
||||||
{
|
|
||||||
write(2, "Unknown read character in map\n", 26);
|
write(2, "Unknown read character in map\n", 26);
|
||||||
exit(84);
|
exit(84);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
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;
|
int i = 0;
|
||||||
|
|
||||||
if (sokoban.map_save[y][x] == '$') {
|
if (sokoban.map_save[y][x] == '$') {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (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;
|
int i = 0;
|
||||||
|
|
||||||
if (sokoban.map_save[y][x] == '@') {
|
if (sokoban.map_save[y][x] == '@') {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (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
|
** Main function for the my_sokoban
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ncurses.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../include/libmy.h"
|
#include "../include/libmy.h"
|
||||||
#include "../include/sokoban.h"
|
#include "../include/sokoban.h"
|
||||||
|
|
||||||
char *open_map(char const *path)
|
char *open_map(char const *path) {
|
||||||
{
|
|
||||||
int reading;
|
int reading;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
|
|
||||||
|
@ -22,58 +22,63 @@ char *open_map(char const *path)
|
||||||
write(2, "No such file or directory\n", 26);
|
write(2, "No such file or directory\n", 26);
|
||||||
exit (84);
|
exit (84);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = read_map(reading);
|
buffer = read_map(reading);
|
||||||
close(reading);
|
close(reading);
|
||||||
return (buffer);
|
return (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *read_map(int reading)
|
char *read_map(int reading) {
|
||||||
{
|
|
||||||
char *buffer = malloc(sizeof(char) * 10000);
|
char *buffer = malloc(sizeof(char) * 10000);
|
||||||
int size = 32;
|
int size = 32;
|
||||||
|
|
||||||
size = read(reading, buffer, 10000);
|
size = read(reading, buffer, 10000);
|
||||||
if (size == -1)
|
if (size == -1) {
|
||||||
exit(84);
|
exit(84);
|
||||||
|
}
|
||||||
|
|
||||||
buffer[size] = '\0';
|
buffer[size] = '\0';
|
||||||
return (buffer);
|
return (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int count_columns(sokoban_t sokoban, int position)
|
int count_columns(sokoban_t sokoban, int position) {
|
||||||
{
|
|
||||||
int columns = 0;
|
int columns = 0;
|
||||||
|
|
||||||
for (; sokoban.buffer[position] != '\n'; position++) {
|
for (; sokoban.buffer[position] != '\n'; position++) {
|
||||||
columns++;
|
columns++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (columns);
|
return (columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
sokoban_t count_lines(sokoban_t sokoban)
|
sokoban_t count_lines(sokoban_t sokoban) {
|
||||||
{
|
|
||||||
sokoban.lines = 0;
|
sokoban.lines = 0;
|
||||||
|
|
||||||
for (int i = 0; sokoban.buffer[i] != '\0'; i++) {
|
for (int i = 0; sokoban.buffer[i] != '\0'; i++) {
|
||||||
if (sokoban.buffer[i] == '\n' || sokoban.buffer[i] == '\0')
|
if (sokoban.buffer[i] == '\n' || sokoban.buffer[i] == '\0') {
|
||||||
sokoban.lines++;
|
sokoban.lines += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sokoban);
|
return (sokoban);
|
||||||
}
|
}
|
||||||
|
|
||||||
sokoban_t make_map(char const *path, sokoban_t sokoban)
|
sokoban_t make_map(char const *path, sokoban_t sokoban) {
|
||||||
{
|
|
||||||
sokoban.buffer = open_map(path);
|
|
||||||
sokoban = count_lines(sokoban);
|
|
||||||
int k = 0;
|
int k = 0;
|
||||||
int columns = 0;
|
int columns = 0;
|
||||||
|
|
||||||
|
sokoban.buffer = open_map(path);
|
||||||
|
sokoban = count_lines(sokoban);
|
||||||
sokoban.num_chars_map = 0;
|
sokoban.num_chars_map = 0;
|
||||||
sokoban.map = malloc(sizeof(char *) * sokoban.lines);
|
sokoban.map = malloc(sizeof(char *) * sokoban.lines);
|
||||||
sokoban.map_save = malloc(sizeof (char *) * sokoban.lines);
|
sokoban.map_save = malloc(sizeof (char *) * sokoban.lines);
|
||||||
|
|
||||||
for (int j = 0; j < sokoban.lines; j++) {
|
for (int j = 0; j < sokoban.lines; j++) {
|
||||||
columns = count_columns(sokoban, k);
|
columns = count_columns(sokoban, k);
|
||||||
sokoban.num_chars_map += columns;
|
sokoban.num_chars_map += columns;
|
||||||
sokoban.map[j] = malloc(sizeof(char) * columns + 1);
|
sokoban.map[j] = malloc(sizeof(char) * columns + 1);
|
||||||
sokoban.map_save[j] = malloc(sizeof(char) * columns + 1);
|
sokoban.map_save[j] = malloc(sizeof(char) * columns + 1);
|
||||||
|
|
||||||
for (int i = 0; i < columns; i++) {
|
for (int i = 0; i < columns; i++) {
|
||||||
sokoban.map[j][i] = sokoban.buffer[k];
|
sokoban.map[j][i] = sokoban.buffer[k];
|
||||||
sokoban.map_save[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';
|
sokoban.map_save[j][i+1] = '\0';
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
|
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sokoban);
|
return (sokoban);
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_goal_cell(int y, int x, sokoban_t sokoban)
|
int is_goal_cell(int y, int x, sokoban_t sokoban) {
|
||||||
{
|
return (sokoban.map_save[y][x] == '.') || \
|
||||||
return (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] == '*');
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
138
src/movement.c
138
src/movement.c
|
@ -5,148 +5,166 @@
|
||||||
** Function that make the player move
|
** Function that make the player move
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ncurses.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../include/libmy.h"
|
#include "../include/libmy.h"
|
||||||
#include "../include/sokoban.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);
|
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);
|
return (sokoban);
|
||||||
} else {
|
} 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] == '.')
|
if (sokoban.map[sokoban.player_y][sokoban.player_x - 2] == '.') {
|
||||||
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 - 2] = '$';
|
||||||
|
}
|
||||||
|
|
||||||
sokoban.map[sokoban.player_y][sokoban.player_x] = ' ';
|
sokoban.map[sokoban.player_y][sokoban.player_x] = ' ';
|
||||||
sokoban.player_x--;
|
sokoban.player_x--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sokoban);
|
return (sokoban);
|
||||||
}
|
}
|
||||||
|
|
||||||
sokoban_t move_box_right(sokoban_t sokoban)
|
sokoban_t move_box_right(sokoban_t sokoban) {
|
||||||
{
|
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] == '*') {
|
sokoban.map[sokoban.player_y][sokoban.player_x + 2] == '*') {
|
||||||
|
|
||||||
return (sokoban);
|
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);
|
return (sokoban);
|
||||||
} else {
|
} 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] == '.')
|
if (sokoban.map[sokoban.player_y][sokoban.player_x + 2] == '.') {
|
||||||
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 + 2] = '$';
|
||||||
|
}
|
||||||
|
|
||||||
sokoban.map[sokoban.player_y][sokoban.player_x] = ' ';
|
sokoban.map[sokoban.player_y][sokoban.player_x] = ' ';
|
||||||
sokoban.player_x++;
|
sokoban.player_x++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sokoban);
|
return (sokoban);
|
||||||
}
|
}
|
||||||
|
|
||||||
sokoban_t move_box_up(sokoban_t sokoban)
|
sokoban_t move_box_up(sokoban_t sokoban) {
|
||||||
{
|
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] == '*') {
|
sokoban.map[sokoban.player_y - 2][sokoban.player_x] == '*') {
|
||||||
|
|
||||||
return (sokoban);
|
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);
|
return (sokoban);
|
||||||
} else {
|
} 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] == '.')
|
if (sokoban.map[sokoban.player_y - 2][sokoban.player_x] == '.') {
|
||||||
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 - 2][sokoban.player_x] = '$';
|
||||||
|
}
|
||||||
|
|
||||||
sokoban.map[sokoban.player_y][sokoban.player_x] = ' ';
|
sokoban.map[sokoban.player_y][sokoban.player_x] = ' ';
|
||||||
sokoban.player_y--;
|
sokoban.player_y--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sokoban);
|
return (sokoban);
|
||||||
}
|
}
|
||||||
|
|
||||||
sokoban_t move_box_down(sokoban_t sokoban)
|
sokoban_t move_box_down(sokoban_t sokoban) {
|
||||||
{
|
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] == '*') {
|
sokoban.map[sokoban.player_y + 2][sokoban.player_x] == '*') {
|
||||||
|
|
||||||
return (sokoban);
|
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);
|
return (sokoban);
|
||||||
} else {
|
} 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.map[sokoban.player_y][sokoban.player_x] = ' ';
|
||||||
sokoban.player_y++;
|
sokoban.player_y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sokoban);
|
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);
|
sokoban = move_box_left(sokoban);
|
||||||
} else {
|
} 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.map[sokoban.player_y][sokoban.player_x] = ' ';
|
||||||
sokoban.player_x--;
|
sokoban.player_x--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sokoban);
|
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] != '#') {
|
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.map[sokoban.player_y][sokoban.player_x + 1] == '*') {
|
||||||
|
|
||||||
sokoban = move_box_right(sokoban);
|
sokoban = move_box_right(sokoban);
|
||||||
} else {
|
} 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.map[sokoban.player_y][sokoban.player_x] = ' ';
|
||||||
sokoban.player_x++;
|
sokoban.player_x++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sokoban);
|
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] != '#') {
|
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.map[sokoban.player_y - 1][sokoban.player_x] == '*') {
|
||||||
|
|
||||||
sokoban = move_box_up(sokoban);
|
sokoban = move_box_up(sokoban);
|
||||||
} else {
|
} 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.map[sokoban.player_y][sokoban.player_x] = ' ';
|
||||||
sokoban.player_y--;
|
sokoban.player_y--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sokoban);
|
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] != '#') {
|
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.map[sokoban.player_y + 1][sokoban.player_x] == '*') {
|
||||||
|
|
||||||
sokoban = move_box_down(sokoban);
|
sokoban = move_box_down(sokoban);
|
||||||
} else {
|
} 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.map[sokoban.player_y][sokoban.player_x] = ' ';
|
||||||
sokoban.player_y++;
|
sokoban.player_y++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sokoban);
|
return (sokoban);
|
||||||
}
|
}
|
||||||
|
|
BIN
src/movement.o
BIN
src/movement.o
Binary file not shown.
47
src/play.c
47
src/play.c
|
@ -7,50 +7,45 @@
|
||||||
** Adapted by Nir Lipo, 2021
|
** Adapted by Nir Lipo, 2021
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ncurses.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../include/libmy.h"
|
#include "../include/libmy.h"
|
||||||
#include "../include/sokoban.h"
|
#include "../include/sokoban.h"
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
* MACROS *
|
* MACROS *
|
||||||
*********/
|
*********/
|
||||||
#include <string.h>
|
|
||||||
#define TERMINAL_TYPE (strcmp(getenv("TERM"), "xterm") == 0 ? "rxvt" : \
|
#define TERMINAL_TYPE (strcmp(getenv("TERM"), "xterm") == 0 ? "rxvt" : \
|
||||||
getenv("TERM"))
|
getenv("TERM"))
|
||||||
SCREEN *mainScreen = NULL;
|
SCREEN *mainScreen = NULL;
|
||||||
WINDOW *mainWindow = NULL;
|
WINDOW *mainWindow = NULL;
|
||||||
|
|
||||||
|
int play(char const *path) {
|
||||||
int play(char const *path)
|
// Load map
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Load Map
|
|
||||||
*/
|
|
||||||
sokoban_t sokoban = make_map(path, sokoban);
|
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);
|
map_check(sokoban);
|
||||||
|
|
||||||
/**
|
// Locate player x,y position
|
||||||
* Locate player x,y position
|
|
||||||
*/
|
|
||||||
sokoban = find_player(sokoban);
|
sokoban = find_player(sokoban);
|
||||||
|
|
||||||
sokoban.base_path = path;
|
|
||||||
|
|
||||||
mainScreen = newterm(TERMINAL_TYPE, stdout, stdin);
|
mainScreen = newterm(TERMINAL_TYPE, stdout, stdin);
|
||||||
set_term(mainScreen);
|
set_term(mainScreen);
|
||||||
int cols = 1;
|
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]);
|
cols = strlen(sokoban.map[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mainWindow = newwin(sokoban.lines, cols, 0, 0);
|
mainWindow = newwin(sokoban.lines, cols, 0, 0);
|
||||||
|
|
||||||
cbreak();
|
cbreak();
|
||||||
|
@ -63,18 +58,18 @@ int play(char const *path)
|
||||||
touchwin(mainWindow);
|
touchwin(mainWindow);
|
||||||
wnoutrefresh(mainWindow);
|
wnoutrefresh(mainWindow);
|
||||||
doupdate();
|
doupdate();
|
||||||
for (int i = 0; i < sokoban.lines; i++)
|
|
||||||
|
for (int i = 0; i < sokoban.lines; i++) {
|
||||||
mvprintw(i, 0, sokoban.map[i]);
|
mvprintw(i, 0, sokoban.map[i]);
|
||||||
|
}
|
||||||
|
|
||||||
move(sokoban.player_y, sokoban.player_x);
|
move(sokoban.player_y, sokoban.player_x);
|
||||||
sokoban = game_management(sokoban);
|
sokoban = game_management(sokoban);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sokoban_t game_management(sokoban_t sokoban)
|
sokoban_t game_management(sokoban_t sokoban) {
|
||||||
{
|
int key_pressed = getch();
|
||||||
int key_pressed = 0;
|
|
||||||
|
|
||||||
key_pressed = getch();
|
|
||||||
sokoban = key_check(sokoban, key_pressed);
|
sokoban = key_check(sokoban, key_pressed);
|
||||||
sokoban = check_zone_reset(sokoban);
|
sokoban = check_zone_reset(sokoban);
|
||||||
loose_check(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
|
** Function that check if the game is won
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ncurses.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../include/libmy.h"
|
#include "../include/libmy.h"
|
||||||
#include "../include/sokoban.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 i = 0; i < sokoban.lines; i++) {
|
||||||
for (int j = 0; sokoban.map_save[i][j] != '\0'; j++) {
|
for (int j = 0; sokoban.map_save[i][j] != '\0'; j++) {
|
||||||
if (sokoban.map[i][j] == '$')
|
if (sokoban.map[i][j] == '$') {
|
||||||
return ;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
endwin();
|
endwin();
|
||||||
exit (0);
|
exit (0);
|
||||||
|
|
||||||
}
|
}
|
BIN
src/win_check.o
BIN
src/win_check.o
Binary file not shown.
|
@ -7,28 +7,25 @@
|
||||||
** Adpated by Nir 2021
|
** Adpated by Nir 2021
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../include/libmy.h"
|
#include "../include/libmy.h"
|
||||||
#include "../include/sokoban.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 - 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 = reset_zone(sokoban.player_y, sokoban.player_x - 1, sokoban);
|
||||||
sokoban = reset_zone(sokoban.player_y, sokoban.player_x-1, sokoban);
|
|
||||||
|
|
||||||
return (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] == ' ') {
|
||||||
if ( is_goal_cell(y, x, sokoban ) && sokoban.map[y][x] == ' ') {
|
|
||||||
sokoban.map[y][x] = '.';
|
sokoban.map[y][x] = '.';
|
||||||
return(sokoban);
|
|
||||||
}
|
}
|
||||||
return (sokoban);
|
return (sokoban);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
BIN
src/zone_check.o
BIN
src/zone_check.o
Binary file not shown.
Loading…
Reference in a new issue