diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..60d4bfa
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.idea/
+cmake-build-*/
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..ae687a8
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 3.22.1)
+project(PacXon C)
+
+set(CMAKE_C_STANDARD 11)
+
+find_package(Curses REQUIRED)
+include_directories(${CURSES_INCLUDE_DIR})
+
+add_executable(PacXon main.c)
+target_link_libraries(PacXon curses)
\ No newline at end of file
diff --git a/PacXon.cbp b/PacXon.cbp
deleted file mode 100755
index 87d0603..0000000
--- a/PacXon.cbp
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/README.md b/README.md
index 10987f4..0bff3b1 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# PacXon
-A partial PacXon game clone in C & Windows cmd.exe (you can play the original version [here](https://www.pacxon.net/)).
+A partial PacXon game clone in C, on CLI (you can play the original version [here](https://www.pacxon.net/)).
This game was my final project for the **computer fundamentals and programming** university course, made in **early 2019**.
@@ -8,6 +8,22 @@ This game was my final project for the **computer fundamentals and programming**
## Simple build & run
-Open the project in Code::Blocks 17.12 (with MinGW) on a Windows OS, and hit Build and run.
+> Pro-tip: use an **IDE** to build and run the project.
-> Running the game might be tricky; because it is left behind as a **legacy**, and it is not packaged properly.
\ No newline at end of file
+### Ubuntu
+
+> Tested on Ubuntu 22.04 LTS.
+
+- `sudo apt install cmake gcc make libncurses-dev`.
+- `cmake . && make && ./PacXon`
+
+Or
+
+- `sudo apt install gcc libncurses-dev`
+- `gcc main.c -lncurses && ./a.out`
+
+### Other Operating Systems, including Windows
+
+Figure it out yourself :slightly_smiling_face:.
+
+> Fow Windows, you can check out earlier commit [765f67781980fb90d9b2bdfef960878687298926](https://github.com/agcom/pacxon/tree/765f67781980fb90d9b2bdfef960878687298926) and follow the instructions there.
\ No newline at end of file
diff --git a/dir.c b/dir.c
new file mode 100644
index 0000000..d7f78ce
--- /dev/null
+++ b/dir.c
@@ -0,0 +1,69 @@
+#ifndef DIR_C_INCLUDED
+#define DIR_C_INCLUDED
+
+#include
+#include "utils.c"
+
+// Directions' masks
+#define VERTICAL 0b0001
+#define HORIZONTAL 0b0010
+#define LEFT 0b0100
+#define UP 0b1000
+
+typedef int dir_t;
+
+// Clock-wise order
+const dir_t all_directions[8] = {
+ VERTICAL | UP, // UP
+ HORIZONTAL | VERTICAL | UP | !LEFT, // Up Right
+ HORIZONTAL | !LEFT, // Right
+ HORIZONTAL | VERTICAL | !UP | !LEFT, // Down Right
+ VERTICAL | !UP, // Down
+ HORIZONTAL | VERTICAL | !UP | LEFT, // Down Left
+ HORIZONTAL | LEFT, // Left
+ HORIZONTAL | VERTICAL | UP | LEFT // Up Left
+};
+
+void print_dir(const dir_t dir) {
+ bool is_vertical_printed = false;
+
+ if (dir & VERTICAL) {
+ if (dir & UP) printf("Up");
+ else printf("Down");
+
+ is_vertical_printed = true;
+ }
+
+ if (dir & HORIZONTAL) {
+ if (is_vertical_printed) printf(" ");
+
+ if (dir & LEFT) printf("Left");
+ else printf("Right");
+ }
+}
+
+void print_dir_arr(const int size, const dir_t dirs[size]) {
+ int i;
+ for (i = 0; i < size; i++) {
+ print_dir(dirs[i]);
+ if (i != size - 1) printf(", ");
+ }
+}
+
+int turn_dir(dir_t dir, const bool clockwise, const int steps) {
+
+ // Find its index at directions
+ int index;
+ if ((index = linear_int_arr_search(8, all_directions, dir)) == -1)
+ return SHOULD_NOT_REACH_HERE; // Not a direction
+
+ int i;
+ for (i = 0; i < steps; i++) {
+ if (clockwise) dir = all_directions[index == 7 ? 0 : index + 1];
+ else dir = all_directions[index == 0 ? 7 : index - 1];
+ }
+
+ return dir;
+}
+
+#endif // DIR_C_INCLUDED
\ No newline at end of file
diff --git a/ghosts.c b/ghosts.c
index 075fd70..02c4261 100755
--- a/ghosts.c
+++ b/ghosts.c
@@ -1 +1,30 @@
-#include "ghosts.h"
+#ifndef GHOSTS_C_INCLUDED
+#define GHOSTS_C_INCLUDED
+
+#include "loc.c"
+
+// Ghosts type coding
+typedef enum {
+ FLOAT_GHOST, RAIL_GHOST, BRICK_ZONE_GHOST
+} ghost_type_t;
+
+// Shapes
+#define FLOAT_GHOST_CHAR "α"
+#define RAIL_GHOST_CHAR "ß"
+#define BRICK_ZONE_GHOST_CHAR "δ"
+
+// Locations needed sizes
+#define FLOAT_GHOST_LOCS_SIZE 1
+#define BRICK_ZONE_GHOST_LOCS_SIZE 1
+#define RAIL_GHOST_LOCS_SIZE 2
+
+#define MAX_GHOST_LOCS_SIZE 2
+
+typedef struct {
+ ghost_type_t type;
+ int locs_size;
+ loc_t locs[MAX_GHOST_LOCS_SIZE];
+ int movement;
+} ghost_t;
+
+#endif // GHOSTS_C_INCLUDED
\ No newline at end of file
diff --git a/ghosts.h b/ghosts.h
deleted file mode 100755
index 5e8116b..0000000
--- a/ghosts.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef GHOSTS_H_INCLUDED
-#define GHOSTS_H_INCLUDED
-
-#include "utils.h"
-
-//ghosts type coding
-#define FLOAT_GHOST 0
-#define RAIL_GHOST 1
-#define BRICK_ZONE_GHOST 2
-
-//shapes
-#define FLOAT_GHOST_CHAR 224
-#define RAIL_GHOST_CHAR 225
-#define BRICK_ZONE_GHOST_CHAR 235
-
-#define A_GHOST_MAX_LOCATIONS 10
-
-#define FLOAT_GHOST_LOCATIONSS 1
-#define BRICK_ZONE_GHOST_LOCATIONSS 1
-#define RAIL_GHOST_LOCATIONSS 2
-
-//a ghost
-typedef struct {
-
- int type;
- int locationss;
- Location locations[A_GHOST_MAX_LOCATIONS];
- int movement;
-
-} Ghost;
-
-#endif // GHOSTS_H_INCLUDED
diff --git a/kbhit.c b/kbhit.c
new file mode 100644
index 0000000..0bffa06
--- /dev/null
+++ b/kbhit.c
@@ -0,0 +1,14 @@
+#ifndef KBHIT_C_INCLUDED
+#define KBHIT_C_INCLUDED
+
+#include
+
+int kbhit() {
+ const int c = getch();
+ if (c != ERR) {
+ ungetch(c);
+ return 1;
+ } else return 0;
+}
+
+#endif // KBHIT_C_INCLUDED
\ No newline at end of file
diff --git a/loc.c b/loc.c
new file mode 100644
index 0000000..b02aa2a
--- /dev/null
+++ b/loc.c
@@ -0,0 +1,106 @@
+#ifndef LOC_C_INCLUDED
+#define LOC_C_INCLUDED
+
+#include
+#include "dir.c"
+#include "utils.c"
+
+// x = row & y = column
+typedef struct {
+ int x, y;
+} loc_t;
+
+void rand_loc(loc_t *p, const int min_x, const int max_x, const int min_y, const int max_y) {
+ p->x = min_x + rand() % (max_x - min_x + 1);
+ p->y = min_y + rand() % (max_y - min_y + 1);
+}
+
+void next_loc(loc_t *next, const dir_t dir) {
+ if (dir & VERTICAL) {
+ if (dir & UP) next->x--;
+ else next->x++;
+ }
+
+ if (dir & HORIZONTAL) {
+ if (dir & LEFT) next->y--;
+ else next->y++;
+ }
+}
+
+int reverse_dir(dir_t dir) {
+ if (dir & HORIZONTAL) dir ^= LEFT;
+ if (dir & VERTICAL) dir ^= UP;
+
+ return dir;
+}
+
+int rand_dir(const bool is_diagonal) {
+ if (is_diagonal) return VERTICAL | HORIZONTAL | (rand_bool() ? LEFT : !LEFT) | (rand_bool() ? UP : !UP);
+ else {
+ const int rnd = rand() % 4;
+ return rnd == 0 ? (HORIZONTAL | LEFT) :
+ rnd == 1 ? (VERTICAL | UP) :
+ rnd == 2 ? (HORIZONTAL | !LEFT) :
+ rnd == 3 ? (VERTICAL | !UP) : SHOULD_NOT_REACH_HERE;
+ }
+
+}
+
+bool are_equal_locs(const loc_t p1, const loc_t p2) {
+ return p1.x == p2.x && p1.y == p2.y;
+}
+
+bool are_neighbour_locs(const loc_t p1, const loc_t p2) {
+ if (are_equal_locs(p1, p2)) return false;
+
+ int i;
+ for (i = 0; i < 8; i++) {
+ loc_t t = p2;
+ next_loc(&t, all_directions[i]);
+ if (are_equal_locs(p1, t)) return true;
+ }
+
+ return false;
+}
+
+void locs_diff_vector(const loc_t p1, const loc_t p2, loc_t *res) {
+ res->x = p2.x - p1.x;
+ res->y = p2.y - p1.y;
+}
+
+int loc_vector_to_dir(const loc_t vector) {
+ if (vector.x < 0 && vector.y < 0) return VERTICAL | HORIZONTAL | LEFT | UP; // Up Left
+ else if (vector.x < 0 && vector.y == 0) return VERTICAL | UP; // Up
+ else if (vector.x < 0 && vector.y > 0) return VERTICAL | HORIZONTAL | !LEFT | UP; // Up Right
+ else if (vector.x == 0 && vector.y < 0) return HORIZONTAL | LEFT; // Left
+ else if (vector.x == 0 && vector.y > 0) return HORIZONTAL | !LEFT; // Right
+ else if (vector.x > 0 && vector.y < 0) return HORIZONTAL | VERTICAL | !UP | LEFT; // Down Left
+ else if (vector.x > 0 && vector.y == 0) return VERTICAL | !UP; // Down
+ else if (vector.x > 0 && vector.y > 0) return VERTICAL | HORIZONTAL | !UP | !LEFT; // Down Right
+ else return SHOULD_NOT_REACH_HERE; // Zero vector
+}
+
+bool are_size_by_size_locs(const loc_t l1, const loc_t l2, const bool check_being_neighbors) {
+ if (check_being_neighbors && !are_neighbour_locs(l1, l2)) return false;
+
+ loc_t vector;
+ locs_diff_vector(l1, l2, &vector);
+
+ const int diff_dir = loc_vector_to_dir(vector);
+ if (diff_dir & VERTICAL && diff_dir & HORIZONTAL) return false;
+ else return true;
+}
+
+void print_loc(const loc_t p) {
+ printf("(%d, %d)", p.x, p.y);
+}
+
+void print_loc_arr(const int size, const loc_t locs[size]) {
+ int i;
+ for (i = 0; i < size; i++) {
+ print_loc(locs[i]);
+ printf(" ");
+ }
+}
+
+#endif // LOC_C_INCLUDED
\ No newline at end of file
diff --git a/main.c b/main.c
index df956e7..23c55cc 100755
--- a/main.c
+++ b/main.c
@@ -10,1008 +10,704 @@ to dos :
- save and load
- levels
- menu
- - reflectDirection method
+ - reflect_dir method (int reflect_dir(const dir_t dir, const int mirror_pos)
- colored char struct
**/
#include
#include
-#include
-#include "utils.h"
-#include "ghosts.h"
-#include "pacman.h"
+#include
+#include
+#include "utils.c"
+#include "ghosts.c"
+#include "pacman.c"
+#include "kbhit.c"
+#include "dir.c"
+#include "loc.c"
-#define MAX_GHOSTS 100 //maximum capacity of the ghosts array
+#define MAX_GHOSTS 100 // Maximum capacity of the ghosts array
-#define REFRESH_RATE 120 //Hz; affects velocity of things in game (pac man, ghosts)
+#define REFRESH_RATE 30 // In Hzs; affects velocity of things in game (pac-man and ghosts).
-//shapes
-#define BRICK_CHAR 178
+// Shapes
+#define BRICK_CHAR "▓"
-//the whole game boar dimensions
+// The whole game board dimensions
#define ROWS 30
#define COLUMNS 70
-#define WIN_PROGRESS 80 //win condition
+#define WIN_PROGRESS 80 // Win percentage
-//global variables
-int float_ghosts = 2;
-int rail_ghosts = 1;
-int brick_zone_ghosts = 0;
-int ghosts_quantity; //count of active ghosts
-Ghost ghosts[MAX_GHOSTS]; //ghosts pool
-int bricks[ROWS][COLUMNS]; //-1 for bricks, >= 0 for zones
-int view_validation = 0; //the drawn picture is the current state or not, if not redraw it
-PacMan pm; //the hero
-char picture[ROWS][COLUMNS]; //the whole things view except the header
-int score = 0; //score
-int progress = 0; //current progress; from 100
-int ghosts_speed_ratio = 3; //ghosts speed = pac man speed / this ratio
+// Ghosts quantity
+#define FLOAT_GHOSTS_COUNT 2
+#define RAIL_GHOSTS_COUNT 1
+#define BRICK_ZONE_GHOSTS_COUNT 0
+#define GHOSTS_SIZE FLOAT_GHOSTS_COUNT + RAIL_GHOSTS_COUNT + BRICK_ZONE_GHOSTS_COUNT // Count of active ghosts
+#define GHOSTS_SPEED_RATIO 3 // Ghosts' speed = pac-man's speed / this ratio
-//how ghosts start
-//f = count of float ghosts
-//r = count of rail ghosts
-//b = count of brick zone ghosts
-//f + r + b == ghosts_quantity
-void initGhosts() {
+ghost_t ghosts[MAX_GHOSTS]; // Ghosts pool
- int append_index = 0;
+int bricks[ROWS][COLUMNS]; // -1 for bricks and >=0 for zones
- int i;
- for(i = 0; i < float_ghosts; i++) { //float ghosts
+pac_man pm; // The hero
- addGhost(FLOAT_GHOST, append_index);
- append_index++;
+char *picture[ROWS][COLUMNS]; // The whole things view except the header
+bool is_view_update = false; // The drawn picture is the current state or not
- }
-
- for(i = 0; i < rail_ghosts; i++) { //rail ghosts
-
- addGhost(RAIL_GHOST, append_index);
- append_index++;
-
- }
-
- for(i = 0; i < brick_zone_ghosts; i++) { //brick zone ghosts
-
- addGhost(BRICK_ZONE_GHOST, append_index);
- append_index++;
-
- }
+int score = 0;
+int progress = 0; // Current progress; from 100.
+bool is_brick_there(const loc_t loc) {
+ // Check location to be in bounds
+ if (loc.x < 0 || loc.x > ROWS - 1 || loc.y < 0 || loc.y > COLUMNS - 1) return false; // Out of bounds location
+ return bricks[loc.x][loc.y] < 0;
}
-//for initGhosts method
-void addGhost(int type, int index) {
-
- ghosts[index].type = type;
-
- switch(type) {
-
- case FLOAT_GHOST : {
-
- ghosts[index].locationss = 1;
- randPoint(&(ghosts[index].locations[0]), 1, ROWS - 2, 1, COLUMNS - 2);
- ghosts[index].movement = randDirection(1);
-
- break;
- }
-
- case RAIL_GHOST : {
-
- ghosts[index].locationss = 2;
-
- int bricks_count = (ROWS * 2 + COLUMNS * 2) - 4; //count of bricks at the start of the game
-
- int rand_room = rand() % bricks_count;
-
- //rand_room to location
- int i, counter = 0;
- for(i = 0; i < ROWS; i++) {
-
- int j;
- for(j = 0; j < COLUMNS; j++) {
-
- if(bricks[i][j] == -1) {
-
- if(counter == rand_room) {
-
- ghosts[index].locations[0].x = i;
- ghosts[index].locations[0].y = j;
-
- //break both loops
- i = ROWS;
- break;
-
- }
-
- counter++;
-
- }
-
- }
-
- }
-
- //choose a random possible direction
- int possiblitites[2];
- int possiblitites_append = 0;
- for(i = 0; i < 8; i++) {
-
- Location t = ghosts[index].locations[0];
- nextLocation(&t, directions[i]);
-
- if(isBrickThere(t)) {
-
- possiblitites[possiblitites_append++] = directions[i];
-
- printf("%d", possiblitites_append);
-
- }
-
- }
-
- ghosts[index].movement = possiblitites[rand()%2];
-
- ghosts[index].locations[1] = ghosts[index].locations[0];
-
- if(ghosts[index].movement & VERTICAL) { //vertical
-
- //left or right
- if(ghosts[index].locations[0].y == 0) { //right
-
- nextLocation(&ghosts[index].locations[1], HORIZONTAL | !LEFT);
-
- } else { //left
-
- nextLocation(&ghosts[index].locations[1], HORIZONTAL | LEFT);
-
- }
-
- } else { //horizontal
-
- //up or down
- if(ghosts[index].locations[0].x == 0) { //down
-
- nextLocation(&ghosts[index].locations[1], VERTICAL | !UP);
-
- } else { //up
-
- nextLocation(&ghosts[index].locations[1], VERTICAL | UP);
-
- }
-
- }
-
- break;
-
- }
-
- case BRICK_ZONE_GHOST : {
-
- //should initialize the location after the first zone captured
- ghosts[index].locationss = 1;
- ghosts[index].locations[0].x = -1;
- ghosts[index].locations[0].y = -1;
- ghosts[index].movement = randDirection(1);
-
- break;
- }
-
- }
-
- index++;
-
+// For initGhosts method
+void add_ghost(const int type, const int index) {
+ ghosts[index].type = type;
+
+ switch (type) {
+ case FLOAT_GHOST : {
+ ghosts[index].locs_size = 1;
+ rand_loc(&(ghosts[index].locs[0]), 1, ROWS - 2, 1, COLUMNS - 2);
+ ghosts[index].movement = rand_dir(1);
+
+ break;
+ }
+ case RAIL_GHOST : {
+ ghosts[index].locs_size = 2;
+
+ const int bricks_count = (ROWS * 2 + COLUMNS * 2) - 4; // Count of bricks at the start of the game
+ const int rand_brick = rand() % bricks_count;
+
+ // rand_room to location
+ int i, counter = 0;
+ for (i = 0; i < ROWS; i++) {
+ int j;
+ for (j = 0; j < COLUMNS; j++) {
+ if (bricks[i][j] == -1) {
+ if (counter == rand_brick) {
+ ghosts[index].locs[0].x = i;
+ ghosts[index].locs[0].y = j;
+
+ // Break both loops
+ i = ROWS;
+ break;
+ }
+ counter++;
+ }
+ }
+ }
+
+ // Choose a random possible direction
+ int possibilities[2];
+ int possibilities_append_index = 0;
+ for (i = 0; i < 8; i++) {
+ loc_t t = ghosts[index].locs[0];
+ next_loc(&t, all_directions[i]);
+
+ if (is_brick_there(t)) {
+ possibilities[possibilities_append_index++] = all_directions[i];
+ }
+ }
+
+ ghosts[index].movement = possibilities[rand() % 2];
+ ghosts[index].locs[1] = ghosts[index].locs[0];
+
+ if (ghosts[index].movement & VERTICAL) { // Vertical: Left or Right
+ if (ghosts[index].locs[0].y == 0) { // Right
+ next_loc(&ghosts[index].locs[1], HORIZONTAL | !LEFT);
+ } else { // Left
+ next_loc(&ghosts[index].locs[1], HORIZONTAL | LEFT);
+ }
+ } else { // Horizontal: Up or Down
+ if (ghosts[index].locs[0].x == 0) { // Down
+ next_loc(&ghosts[index].locs[1], VERTICAL | !UP);
+ } else { // Up
+ next_loc(&ghosts[index].locs[1], VERTICAL | UP);
+ }
+ }
+
+ break;
+ }
+
+ case BRICK_ZONE_GHOST : {
+ // Should initialize the location after the first zone captured
+ ghosts[index].locs_size = 1;
+ ghosts[index].locs[0].x = -1;
+ ghosts[index].locs[0].y = -1;
+ ghosts[index].movement = rand_dir(1);
+
+ break;
+ }
+
+ }
}
-//how pac man starts
-void initPacMan() {
-
- pm.location.x = 0;
- pm.location.y = 0;
-
- pm.movement = -1;
- pm.lives = 3;
-
+void init_ghosts() {
+ int append_index = 0;
+
+ int i;
+ for (i = 0; i < FLOAT_GHOSTS_COUNT; i++) {
+ add_ghost(FLOAT_GHOST, append_index);
+ append_index++;
+ }
+
+ for (i = 0; i < RAIL_GHOSTS_COUNT; i++) {
+ add_ghost(RAIL_GHOST, append_index);
+ append_index++;
+ }
+
+ for (i = 0; i < BRICK_ZONE_GHOSTS_COUNT; i++) {
+ add_ghost(BRICK_ZONE_GHOST, append_index);
+ append_index++;
+ }
}
-//bricks layout at the start
-void initBricks() {
-
- int i;
- for(i = 0; i < ROWS; i++) {
-
- int j;
- for(j = 0; j < COLUMNS; j++) {
-
- if(i == 0 || i == ROWS - 1 || j == 0 || j == COLUMNS - 1) bricks[i][j] = -1;
- else bricks[i][j] = 0; //first zone
-
- }
-
- }
-
+void init_pac_man() {
+ pm.location.x = 0;
+ pm.location.y = 0;
+
+ pm.movement = -1;
+ pm.lives = 3;
}
-//draws whole things
-void drawGame() {
-
- if(view_validation) return;
-
- updatePicture();
-
- cls();
-
- //print the header
- drawHeader();
-
- //print the picture
- print2DCharArray(ROWS, COLUMNS, picture);
-
+// Initial bricks layout
+void init_bricks() {
+ int i;
+ for (i = 0; i < ROWS; i++) {
+ int j;
+ for (j = 0; j < COLUMNS; j++) {
+ if (i == 0 || i == ROWS - 1 || j == 0 || j == COLUMNS - 1) bricks[i][j] = -1;
+ else bricks[i][j] = 0; // First zone
+ }
+ }
}
-void init() {
-
- ghosts_quantity = float_ghosts + rail_ghosts + brick_zone_ghosts;
-
- initBricks();
- initGhosts();
- initPacMan();
-
+void update_picture() {
+ int i;
+ for (i = 0; i < ROWS; i++) {
+ int j;
+ for (j = 0; j < COLUMNS; j++) {
+ if (bricks[i][j] == -1) picture[i][j] = BRICK_CHAR;
+ else if (bricks[i][j] == -2) picture[i][j] = PAC_MAN_TRACE_CHAR;
+ else picture[i][j] = " "; // Empty
+ }
+ }
+
+ // Add pac-man
+ picture[pm.location.x][pm.location.y] = PAC_MAN_CHAR;
+
+ // Add ghosts
+ for (i = 0; i < GHOSTS_SIZE; i++) {
+ int j;
+ for (j = 0; j < ghosts[i].locs_size; j++) {
+ picture[ghosts[i].locs[j].x][ghosts[i].locs[j].y] = (
+ ghosts[i].type == FLOAT_GHOST ? FLOAT_GHOST_CHAR :
+ ghosts[i].type == RAIL_GHOST ? RAIL_GHOST_CHAR :
+ ghosts[i].type == BRICK_ZONE_GHOST ? BRICK_ZONE_GHOST_CHAR :
+ ""
+ );
+ }
+ }
+
+ is_view_update = true;
}
-void updatePicture() {
-
- int i;
- for(i = 0; i < ROWS; i++) {
-
- int j;
- for(j = 0; j < COLUMNS; j++) {
-
- if(bricks[i][j] == -1) picture[i][j] = BRICK_CHAR; //brick here
- else if(bricks[i][j] == -2) picture[i][j] = PAC_MAN_TRACE_CHAR;//pacman trace
- else picture[i][j] = ' '; //empty
-
- }
-
- }
-
- //add pac man
- picture[pm.location.x][pm.location.y] = PAC_MAN_CHAR;
-
- //add ghosts
- for(i = 0; i < ghosts_quantity; i++) {
-
- int j;
- for(j = 0; j < ghosts[i].locationss; j++) {
-
- picture[ghosts[i].locations[j].x][ghosts[i].locations[j].y] = (ghosts[i].type == FLOAT_GHOST ? FLOAT_GHOST_CHAR : ghosts[i].type == RAIL_GHOST ? RAIL_GHOST_CHAR : ghosts[i].type == BRICK_ZONE_GHOST ? BRICK_ZONE_GHOST_CHAR : SHOULD_NOT_REACH_HERE);
-
- }
-
-
- }
-
- view_validation = 1;
-
+void draw_header() {
+ printf("Lives: %d\tScore: %d\tProgress: %d/%d%%\r\n", pm.lives, score, progress, WIN_PROGRESS);
}
-void drawHeader() {
-
- printf("Lives: %d\tScore: %d\tProgress: %d/%d%c\n", pm.lives, score, progress, WIN_PROGRESS, PERCENT_CHAR);
-
+// Draws everything
+void draw_game() {
+ if (is_view_update) return;
+
+ update_picture();
+ clear_screen();
+ draw_header();
+ print_2d_str_arr(ROWS, COLUMNS, picture);
}
-void controlAutoMoves() {
-
- moveGhosts();
-
- if(pm.movement != -1) movePacMan(pm.movement, 1);
-
+void init() {
+ init_bricks();
+ init_ghosts();
+ init_pac_man();
}
-//controls ghosts movement
-void moveGhosts() {
-
- static int called_times = 0;
- called_times++;
-
- if(called_times == ghosts_speed_ratio) {
-
- int i;
- for(i = 0; i < ghosts_quantity; i++) {
-
- moveGhost(i);
-
- }
-
- called_times = 0;
-
- }
-
+void move_ghost(const int index) {
+ switch (ghosts[index].type) {
+ case FLOAT_GHOST : {
+ if (ghosts[index].movement == -1) break;
+
+ loc_t next = ghosts[index].locs[0];
+ next_loc(&next, ghosts[index].movement);
+
+ if (!is_brick_there(next)) { // Execute the move
+ ghosts[index].locs[0] = next;
+ is_view_update = 0;
+ } else { // Opposite the vertical movement
+ ghosts[index].movement = ghosts[index].movement ^ UP; // Opposite it
+
+ // Reset the point
+ next = ghosts[index].locs[0];
+ next_loc(&next, ghosts[index].movement);
+
+ if (!is_brick_there(next)) { // Execute the move
+ ghosts[index].locs[0] = next;
+ is_view_update = 0;
+ } else { // Opposite the horizontal movement
+ ghosts[index].movement = ghosts[index].movement ^ UP; // Undo vertical changes
+ ghosts[index].movement = ghosts[index].movement ^ LEFT; // Opposite it
+
+ // Reset the point
+ next = ghosts[index].locs[0];
+ next_loc(&next, ghosts[index].movement);
+
+ if (!is_brick_there(next)) { // Execute the move
+ ghosts[index].locs[0] = next;
+ is_view_update = 0;
+ } else { // Reverse both movements
+ ghosts[index].movement = ghosts[index].movement ^ UP;
+
+ // Reset the point
+ next = ghosts[index].locs[0];
+ next_loc(&next, ghosts[index].movement);
+
+ if (!is_brick_there(next)) { // Execute the move
+ ghosts[index].locs[0] = next;
+ is_view_update = 0;
+ } else { // Stuck in a rail; find possible moving directions.
+
+ int pdai = 0; // Possible Directions Append Index
+ int possible_dirs[4];
+
+ int j;
+ for (j = 0; j < 8; j++) {
+ if (all_directions[j] & VERTICAL && all_directions[j] & HORIZONTAL)
+ continue; // Skip 2D directions
+
+ loc_t t = ghosts[index].locs[0];
+ next_loc(&t, all_directions[j]);
+
+ if (!is_brick_there(t)) { // Add
+ possible_dirs[pdai++] = all_directions[j];
+ }
+ }
+
+ if (pdai == 0); // Actually stuck
+ else {
+ // Undo changes
+ ghosts[index].movement = reverse_dir(ghosts[index].movement);
+
+ // Find nearest direction to current moving direction from possible_dirs
+ int nearest_dir_index = -1;
+ int nearest_dir_changes = -1;
+
+ // Clock-wise and non
+ for (j = 0; j <= 1; j++) {
+ int k;
+ for (k = 0; k < pdai; k++) {
+ int changes = 0;
+ int direction = ghosts[index].movement;
+
+ while (direction != possible_dirs[k]) {
+ direction = turn_dir(direction, j, 1);
+ changes++;
+ }
+
+ if (nearest_dir_index == -1 || changes < nearest_dir_changes) {
+ nearest_dir_index = k;
+ nearest_dir_changes = changes;
+ }
+ }
+ }
+
+ // Update direction on this algorithm
+
+ if (pdai == 1) {
+ ghosts[index].movement = reverse_dir(ghosts[index].movement);
+ } else {
+ if (possible_dirs[nearest_dir_index] & HORIZONTAL) {
+ ghosts[index].movement ^= UP;
+ } else { // Vertical
+ ghosts[index].movement ^= LEFT;
+ }
+ }
+
+ // Move on nearest direction
+ next_loc(&ghosts[index].locs[0], possible_dirs[nearest_dir_index]);
+ is_view_update = 0;
+ }
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case RAIL_GHOST : {
+ // First and second locations should be sync
+ int fpai = 0; // First Possibilities Append Index
+ int first_possibilities[4];
+
+ int spai = 0; // Second Possibilities Append Index
+ int second_possibilities[4];
+
+ // Check first location moving possibilities
+ int j;
+ for (j = 0; j < 8; j++) {
+ if (all_directions[j] & VERTICAL && all_directions[j] & HORIZONTAL) continue; //skip 2D directions
+
+ loc_t next = ghosts[index].locs[0];
+ next_loc(&next, all_directions[j]);
+
+ if (is_brick_there(next)) { //possible
+ first_possibilities[fpai++] = all_directions[j];
+ }
+ }
+
+ // Check second location moving possibilities
+ for (j = 0; j < 8; j++) {
+ if (all_directions[j] & VERTICAL && all_directions[j] & HORIZONTAL) continue; // Skip 2D directions
+
+ loc_t next = ghosts[index].locs[1];
+ next_loc(&next, all_directions[j]);
+
+ if (!is_brick_there(next)) { // Possible
+ second_possibilities[spai++] = all_directions[j];
+ }
+ }
+
+ // Current moving direction possibility
+ int first_possibility = linear_int_arr_search(fpai, first_possibilities, ghosts[index].movement) != -1;
+ int second_possibility = linear_int_arr_search(spai, second_possibilities, ghosts[index].movement) != -1;
+
+ int should_change_first_direction = 0;
+ int should_change_second_direction = 0;
+
+ if (first_possibility) {
+ loc_t next = ghosts[index].locs[0];
+ next_loc(&next, ghosts[index].movement);
+
+ // Check to stay neighbors
+ if (are_neighbour_locs(next, ghosts[index].locs[1])) { // Execute it
+ ghosts[index].locs[0] = next;
+ is_view_update = 0;
+ } else should_change_first_direction = 1;
+ } else should_change_first_direction = 1;
+ if (second_possibility) {
+ loc_t next = ghosts[index].locs[1];
+ next_loc(&next, ghosts[index].movement);
+
+ // Check to stay neighbors
+ if (are_neighbour_locs(next, ghosts[index].locs[0])) { // Execute it
+ ghosts[index].locs[1] = next;
+ is_view_update = 0;
+ } else should_change_second_direction = 1;
+ } else should_change_second_direction = 1;
+
+ if (should_change_first_direction && should_change_second_direction) {
+ // Find common possible directions then remove the reverse of current direction
+ int commons[2];
+ int cai = find_common_elements_of_int_arrs(
+ 2, fpai, spai, commons,
+ first_possibilities, second_possibilities
+ ); // Commons' append index
+
+ if (cai != 0) { // Found some commons
+ // Remove the reverse of current direction
+ if (shift_left_int_arr(
+ cai, commons,
+ linear_int_arr_search(cai, commons, reverse_dir(ghosts[index].movement))
+ )) {
+ cai--;
+ } else bug_alert("Reverse of current direction not removed!\n");
+
+ if (cai != 0) {
+ ghosts[index].movement = commons[0];
+ // If ghosts are not side by side, reach that, else normal move.
+ if (!are_size_by_size_locs(
+ ghosts[index].locs[1], ghosts[index].locs[0],
+ 0
+ )) { // Are not side by size
+ loc_t next = ghosts[index].locs[0];
+ next_loc(&next, ghosts[index].movement);
+
+ // Check if now side by side
+ if (!are_size_by_size_locs(ghosts[index].locs[1], next, 0)) { //are not side by side
+ next = ghosts[index].locs[1];
+ next_loc(&next, ghosts[index].movement);
+
+ // Check if now side by side
+ if (!are_size_by_size_locs(next, ghosts[index].locs[0], 0)) { // Stuck
+ // WTF
+ } else { // Execute
+ ghosts[index].locs[1] = next;
+ is_view_update = 0;
+ }
+ } else { // Are side by side; execute the move.
+ ghosts[index].locs[0] = next;
+ is_view_update = 0;
+ }
+ } else { // Are side by side; do a normal move.
+ move_ghost(index);
+ }
+ } else { // No commons after removing reverse direction of current moving direction
+
+ // Find a direction based on being side by side but not reverse of current direction
+ for (j = 0; j < 8; j++) {
+ if ((all_directions[j] & VERTICAL && all_directions[j] & HORIZONTAL) ||
+ all_directions[j] == reverse_dir(ghosts[index].movement))
+ continue; // Skip 2D directions and reverse direction of current direction
+
+ loc_t next = ghosts[index].locs[0];
+ next_loc(&next, all_directions[j]);
+
+ if (is_brick_there(next)) { // Check to be side by side
+ if (!are_size_by_size_locs(ghosts[index].locs[1], next, 0)) {
+ continue; // Not side by side
+ } else { // Found it; execute the move.
+ ghosts[index].movement = all_directions[j];
+ move_ghost(index);
+ break;
+ }
+ }
+ }
+ }
+ } else { // Stuck
+
+ // Find a direction based on being side by side but not reverse of current direction
+ for (j = 0; j < 8; j++) {
+ if ((all_directions[j] & VERTICAL && all_directions[j] & HORIZONTAL) ||
+ all_directions[j] == reverse_dir(ghosts[index].movement))
+ continue; // Skip 2D directions and reverse direction of current direction
+
+ loc_t next = ghosts[index].locs[0];
+ next_loc(&next, all_directions[j]);
+
+ if (is_brick_there(next)) {
+ if (!are_size_by_size_locs(ghosts[index].locs[1], next, 0)) continue; // Not side by side
+ else { // Found it; execute the move
+ ghosts[index].movement = all_directions[j];
+ move_ghost(index);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case BRICK_ZONE_GHOST : {
+ // TODO
+ break;
+ }
+ }
}
-void moveGhost(int i) {
-
- switch(ghosts[i].type) {
-
- case FLOAT_GHOST : {
-
- if(ghosts[i].movement == -1) break;
-
- Location next = ghosts[i].locations[0];
-
- nextLocation(&next, ghosts[i].movement);
-
- if(!isBrickThere(next)) { //execute the move
-
- ghosts[i].locations[0] = next;
- view_validation = 0;
-
- } else { //opposite the vertical movement
-
- ghosts[i].movement = ghosts[i].movement ^ UP; //opposite it
- //reset the point
- next = ghosts[i].locations[0];
- nextLocation(&next, ghosts[i].movement);
-
- if(!isBrickThere(next)) { //execute the move
-
- ghosts[i].locations[0] = next;
- view_validation = 0;
-
- } else { //opposite the horizontal movement
-
- ghosts[i].movement = ghosts[i].movement ^ UP; //undo vertical changes
- ghosts[i].movement = ghosts[i].movement ^ LEFT; //opposite it
- //reset the point
- next = ghosts[i].locations[0];
- nextLocation(&next, ghosts[i].movement);
-
- if(!isBrickThere(next)) { //execute the move
-
- ghosts[i].locations[0] = next;
- view_validation = 0;
-
- } else { //reverse both movements
-
- ghosts[i].movement = ghosts[i].movement ^ UP;
- //reset the point
- next = ghosts[i].locations[0];
- nextLocation(&next, ghosts[i].movement);
-
- if(!isBrickThere(next)) { //execute the move
-
- ghosts[i].locations[0] = next;
- view_validation = 0;
-
- } else { //stuck
-
- //stuck in a rail
-
- //find possible moving directions
-
- int pdai = 0; //possible directions append index
- int possible_directions[4];
-
- int j;
- for(j = 0; j < 8; j++) {
-
- if(directions[j] & VERTICAL && directions[j] & HORIZONTAL) continue; //skip 2D directions
-
- Location t = ghosts[i].locations[0];
- nextLocation(&t, directions[j]);
-
- if(!isBrickThere(t)) { //add
-
- possible_directions[pdai++] = directions[j];
-
- }
-
- }
-
- //debug
-// printf("possible directions : ");
-// printDirectionsArray(pdai, possible_directions);
-// printf("\n");
-
- if(pdai == 0); //actually stuck
- else {
-
- //undo changes
- ghosts[i].movement = reverseDirection(ghosts[i].movement);
-
- //debug
-// printf("current direction : ");
-// printDirection(ghosts[i].movement);
-// printf("\n");
-
- //find nearest direction to current moving direction from possible_directions
- int nearest_direction_index = -1;
- int nearest_direction_changes = -1;
-
- //clockwise and non
- for(j = 0; j <= 1; j++) {
-
- int k;
- for(k = 0; k < pdai; k++) {
-
- int changes = 0;
- int direction = ghosts[i].movement;
-
- while(direction != possible_directions[k]) {
-
- direction = turnDirection(direction, j, 1);
- changes++;
-
- }
-
- if(nearest_direction_index == -1 || changes < nearest_direction_changes) {
-
- nearest_direction_index = k;
- nearest_direction_changes = changes;
-
- }
-
-// printf("%s To ", j == 1 ? "clockwise" : "non_clockwise");
-// printDirection(possible_directions[k]);
-// printf(" = %d\t", changes);
-
- }
-
- }
-
- //update direction on this algorithm
-
- if(pdai == 1) {
-
- ghosts[i].movement = reverseDirection(ghosts[i].movement);
-
- } else {
-
- if(possible_directions[nearest_direction_index] & HORIZONTAL) {
-
- ghosts[i].movement ^= UP;
-
- } else { //vertical
-
- ghosts[i].movement ^= LEFT;
-
- }
-
- }
-
- //move on nearest direction
- nextLocation(&ghosts[i].locations[0], possible_directions[nearest_direction_index]);
- view_validation = 0;
-
- }
-
- }
-
- }
-
- }
-
- }
-
- break;
- }
-
- case RAIL_GHOST : {
-
- //first and second locations should be sync
-
- int fpai = 0; //first possibilities append index
- int first_possibilities[4];
-
- int spai = 0; //second possibilities append index
- int second_possibilities[4];
-
- //check first location moving possibilities
- int j;
- for(j = 0; j < 8; j++) {
-
- if(directions[j] & VERTICAL && directions[j] & HORIZONTAL) continue; //skip 2D directions
-
- Location next = ghosts[i].locations[0];
- nextLocation(&next, directions[j]);
-
- if(isBrickThere(next)) { //possible
-
- first_possibilities[fpai++] = directions[j];
-
- }
-
- }
-
- //check second location moving possibilities
- for(j = 0; j < 8; j++) {
-
- if(directions[j] & VERTICAL && directions[j] & HORIZONTAL) continue; //skip 2D directions
-
- Location next = ghosts[i].locations[1];
- nextLocation(&next, directions[j]);
-
- if(!isBrickThere(next)) { //possible
-
- second_possibilities[spai++] = directions[j];
-
- }
-
- }
-
- //current moving direction possibility
- int first_possibility = linearIntArraySearch(fpai, first_possibilities, ghosts[i].movement) != -1;
- int second_possibility = linearIntArraySearch(spai, second_possibilities, ghosts[i].movement) != -1;
-
- int should_change_first_direction = 0;
- int should_change_second_direction = 0;
-
- if(first_possibility) {
-
- Location next = ghosts[i].locations[0];
- nextLocation(&next, ghosts[i].movement);
-
- //check to stay neighbors
- if(areNeighborPoints(next, ghosts[i].locations[1])) { //execute it
-
- ghosts[i].locations[0] = next;
- view_validation = 0;
-
- } else should_change_first_direction = 1;
-
- } else should_change_first_direction = 1;
-
- if(second_possibility) {
-
- Location next = ghosts[i].locations[1];
- nextLocation(&next, ghosts[i].movement);
-
- //check to stay neighbors
- if(areNeighborPoints(next, ghosts[i].locations[0])) { //execute it
-
- ghosts[i].locations[1] = next;
- view_validation = 0;
-
- } else should_change_second_direction = 1;
-
- } else should_change_second_direction = 1;
-
- if(should_change_first_direction && should_change_second_direction) {
-
- //find common possible directions then remove the reverse of current direction
- int commons[2];
- int cai = findCommonElementsOfIntArrays(2, fpai, spai, commons, first_possibilities, second_possibilities); //commons append index
-
- if(cai != 0) { //found some commons
-
-// printf("remove index : %d\n", linearIntArraySearch(cai, commons, reverseDirection(ghosts[i].movement)));
-// printf("commons before remove %d : ", cai);
-// printDirectionsArray(cai, commons);
-// printf("\n");
-//
-// printf("first p %d : ", fpai);
-// printDirectionsArray(fpai, first_possibilities);
-// printf("\n");
-//
-// printf("second p %d : ", spai);
-// printDirectionsArray(spai, second_possibilities);
-// printf("\n");
-
- //remove the reverse of current direction
- if(shiftLeftIntArray(cai, commons, linearIntArraySearch(cai, commons, reverseDirection(ghosts[i].movement)))) cai--;
-// else bugAlert("reverse of current direction not removed!\n");
-
-// printf("commons %d : ", cai);
-// printDirectionsArray(cai, commons);
-// printf("\n");
-// printf("current movement : ");
-// printDirection(ghosts[i].movement);
-// printf("\n");
-// printf("reverse of current movement : ");
-// printDirection(reverseDirection(ghosts[i].movement));
-// printf("\n");
-// Sleep(1000);
-
- if(cai != 0) {
-
- ghosts[i].movement = commons[0];
-
- //if ghosts are not side by side reach that else normal move
- if(!areSideBySideLocations(ghosts[i].locations[1], ghosts[i].locations[0], 0)) { //are not side by side
-
-// bugAlert("are not sbs\n");
-
- Location next = ghosts[i].locations[0];
- nextLocation(&next, ghosts[i].movement);
-
- //check if now side by side
- if(!areSideBySideLocations(ghosts[i].locations[1], next, 0)) { //are not side by side
-
- next = ghosts[i].locations[1];
- nextLocation(&next, ghosts[i].movement);
-
- //check if now side by side
- if(!areSideBySideLocations(next, ghosts[i].locations[0], 0)) { //stuck
-
- ///wtf
-
- } else { //execute
-
- ghosts[i].locations[1] = next;
- view_validation = 0;
-
- }
-
- } else { //are side by side; execute the move
-
- ghosts[i].locations[0] = next;
- view_validation = 0;
-
- }
-
- } else { //are side by side; do a normal move
-
- moveGhost(i);
-
- }
-
- } else { //no commons after removing reverse direction of current moving direction
-
- //find a direction based on being side by side but not reverse of current direction
- for(j = 0; j < 8; j++) {
-
- if((directions[j] & VERTICAL && directions[j] & HORIZONTAL) || directions[j] == reverseDirection(ghosts[i].movement)) continue; //skip 2D directions and reverse direction of current direction
-
- Location next = ghosts[i].locations[0];
- nextLocation(&next, directions[j]);
-
- if(isBrickThere(next)) { //check to be side by side
-
-// printf("sbs = ");
-// printDirection(sbs);
-// printf("\n");
-
- if(!areSideBySideLocations(ghosts[i].locations[1], next, 0)) continue; //not side by side
- else { //found it; execute the move
-
-// printf("found it : ");
-// printDirection(directions[j]);
-// printf("\n");
-// Sleep(1000);
-
- ghosts[i].movement = directions[j];
-
- moveGhost(i);
-
- break;
-
- }
-
- }
-
- }
-
- }
-
- } else { //stuck
-
-// printf("stuckio!\n");
-
- //find a direction based on being side by side but not reverse of current direction
- for(j = 0; j < 8; j++) {
-
- if((directions[j] & VERTICAL && directions[j] & HORIZONTAL) || directions[j] == reverseDirection(ghosts[i].movement)) continue; //skip 2D directions and reverse direction of current direction
-
- Location next = ghosts[i].locations[0];
- nextLocation(&next, directions[j]);
-
- if(isBrickThere(next)) {
-
-// printf("sbs = ");
-// printDirection(sbs);
-// printf("\n");
-
- if(!areSideBySideLocations(ghosts[i].locations[1], next, 0)) continue; //not side by side
- else { //found it; execute the move
-
-// printf("found it : ");
-// printDirection(directions[j]);
-// printf("\n");
-// Sleep(1000);
-
- ghosts[i].movement = directions[j];
-
- moveGhost(i);
-
- break;
-
- }
-
- }
-
- }
-
- }
-
- }
-
- break;
- }
-
- case BRICK_ZONE_GHOST : {
-
- ///
-
- break;
- }
-
- }
-
+// Controls ghosts movement
+void move_ghosts() {
+ static int called_times = 0;
+ called_times++;
+
+ if (called_times == GHOSTS_SPEED_RATIO) {
+ int i;
+ for (i = 0; i < GHOSTS_SIZE; i++) {
+ move_ghost(i);
+ }
+
+ called_times = 0;
+ }
}
-int isBrickThere(Location p) {
-
- //check location to be in bounds
- if(p.x < 0 || p.x > ROWS - 1 || p.y < 0 || p.y > COLUMNS - 1) return 0; //out of bound location
-
- return bricks[p.x][p.y] < 0;
-
+bool can_pac_man_move(const dir_t dir) {
+ if (dir & HORIZONTAL) {
+ if (dir & LEFT) return pm.location.y - 1 >= 0; // Left
+ else return pm.location.y + 1 < COLUMNS; // Right
+ } else if (dir & VERTICAL) {
+ if (dir & UP) return pm.location.x - 1 >= 0; // Up
+ else return pm.location.x + 1 < ROWS; // Down
+ } else return SHOULD_NOT_REACH_HERE;
}
-int canPacManMove(int direction) {
-
- if(direction & HORIZONTAL) {
-
- if(direction & LEFT) return pm.location.y - 1 >= 0; //left
- else return pm.location.y + 1 < COLUMNS; //right
-
- }
-
- if(direction & VERTICAL) {
-
- if(direction & UP) return pm.location.x - 1 >= 0; //up
- else return pm.location.x + 1 < ROWS; //down
-
- }
-
- return SHOULD_NOT_REACH_HERE;
-
+void update_zones() {
+ int current_color = 0;
+ int current_color_use_time = 0;
+
+ // Replace pac-man trace with bricks
+ replace_2d_int_arr(ROWS, COLUMNS, bricks, -2, -1);
+
+ int i;
+ for (i = 0; i < ROWS; i++) {
+ int j;
+ for (j = 0; j < COLUMNS; j++) {
+ if (bricks[i][j] == -1) {
+ if (current_color_use_time > 0) current_color++;
+ } else {
+ bricks[i][j] = current_color;
+ current_color_use_time++;
+ }
+ }
+ }
+
+ for (i = 0; i < ROWS; i++) {
+ int j;
+ for (j = 0; j < COLUMNS; j++) {
+ if (bricks[i][j] != -1) {
+ // Check neighbors
+ loc_t l;
+
+ int k;
+ for (k = 0; k < 8; k++) {
+ // Reset
+ l.x = i;
+ l.y = j;
+
+ next_loc(&l, all_directions[k]);
+
+ if (bricks[l.x][l.y] == -1) continue;
+ else { // A zone number
+ int o;
+ for (o = 0; o < ROWS; o++) {
+ int p;
+ for (p = 0; p < COLUMNS; p++) {
+ if (bricks[o][p] == -1) continue;
+ else if (bricks[o][p] == bricks[i][j]) bricks[o][p] = bricks[l.x][l.y];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
-void updateZones() {
-
- int current_color = 0;
- int current_color_use_time = 0;
-
- //replace pac man trace with bricks
- Replace2DintArray(ROWS, COLUMNS, bricks, -2, -1);
-
- int i;
- for(i = 0; i < ROWS; i++) {
-
- int j;
- for(j = 0; j < COLUMNS; j++) {
-
- if(bricks[i][j] == -1) {
-
- if(current_color_use_time > 0) current_color++;
-
- } else {
-
- bricks[i][j] = current_color;
- current_color_use_time++;
-
- }
-
- }
-
- }
-
- for(i = 0; i < ROWS; i++) {
-
- int j;
- for(j = 0; j < COLUMNS; j++) {
-
- if(bricks[i][j] != -1) {
-
- //check neighbors
- Location l;
-
- int k;
- for(k = 0; k < 8; k++) {
-
- //reset
- l.x = i;
- l.y = j;
-
- nextLocation(&l, directions[k]);
-
- if(bricks[l.x][l.y] == -1) continue;
- else { //a zone number
-
- int o;
- for(o = 0; o < ROWS; o++) {
-
- int p;
- for(p = 0; p < COLUMNS; p++) {
-
- if(bricks[o][p] == -1) continue;
- else if(bricks[o][p] == bricks[i][j]) bricks[o][p] = bricks[l.x][l.y];
-
- }
-
- }
-
- }
-
- }
-
- }
-
- }
-
- }
-
+void try_capture_zones() {
+ int ghosts_zones[FLOAT_GHOSTS_COUNT * FLOAT_GHOST_LOCS_SIZE + RAIL_GHOSTS_COUNT * RAIL_GHOST_LOCS_SIZE +
+ BRICK_ZONE_GHOSTS_COUNT * BRICK_ZONE_GHOST_LOCS_SIZE];
+
+ int i;
+ for (i = 0; i < GHOSTS_SIZE; i++) {
+ int j;
+ for (j = 0; j < ghosts[i].locs_size; j++) {
+ ghosts_zones[i] = bricks[ghosts[i].locs[j].x][ghosts[i].locs[j].y];
+ }
+ }
+
+ for (i = 0; i < ROWS; i++) {
+ int j;
+ for (j = 0; j < COLUMNS; j++) {
+ if (bricks[i][j] == -1) continue;
+ else if (linear_int_arr_search(GHOSTS_SIZE, ghosts_zones, bricks[i][j]) == -1) {
+ replace_2d_int_arr(ROWS, COLUMNS, bricks, bricks[i][j], -1);
+ }
+ }
+ }
}
-void tryCaptureZones() {
-
- int ghosts_zones[float_ghosts * FLOAT_GHOST_LOCATIONSS + rail_ghosts * RAIL_GHOST_LOCATIONSS + brick_zone_ghosts * BRICK_ZONE_GHOST_LOCATIONSS];
-
- int i;
- for(i = 0; i < ghosts_quantity; i++) {
-
- int j;
- for(j = 0; j < ghosts[i].locationss; j++) {
-
- ghosts_zones[i] = bricks[ghosts[i].locations[j].x][ghosts[i].locations[j].y];
-
- }
-
- }
-
- for(i = 0; i < ROWS; i++) {
-
- int j;
- for(j = 0; j < COLUMNS; j++) {
-
- if(bricks[i][j] == -1) continue;
- else if(linearIntArraySearch(ghosts_quantity, ghosts_zones, bricks[i][j]) == -1) {
-
- Replace2DintArray(ROWS, COLUMNS, bricks, bricks[i][j], -1);
-
- }
-
- }
-
- }
-
+void update_progress() {
+ int bricks_count = 0;
+
+ int i;
+ for (i = 0; i < ROWS; i++) {
+ int j;
+ for (j = 0; j < COLUMNS; j++) {
+ if (bricks[i][j] == -1) bricks_count++;
+ }
+ }
+
+ static int all_bricks_count = (ROWS - 2) * (COLUMNS - 2);
+
+ progress = (int) ((float) (bricks_count - (2 * (ROWS + COLUMNS))) / (float) all_bricks_count * 100);
+ is_view_update = 0;
}
-void updateProgress() {
-
- int bricks_count = 0;
-
- int i;
- for(i = 0; i < ROWS; i++) {
-
- int j;
- for(j = 0; j < COLUMNS; j++) {
-
- if(bricks[i][j] == -1) bricks_count++;
-
- }
-
- }
-
- static int all_bricks_count = (ROWS - 2) * (COLUMNS - 2);
-
- progress = ((float) bricks_count - (2 * (ROWS + COLUMNS))) / (float) all_bricks_count * 100;
- view_validation = 0;
-
+bool move_pac_man(const dir_t dir, const int auto_call) {
+ if (!can_pac_man_move(dir)) return false;
+
+ if (!auto_call && pm.movement != -1) {
+ if (reverse_dir(pm.movement) != dir) pm.movement = dir;
+ return true;
+ }
+
+ next_loc(&pm.location, dir);
+
+ if (bricks[pm.location.x][pm.location.y] != -1) { // Stepped out of the safe zone, run!
+ bricks[pm.location.x][pm.location.y] = -2;
+
+ pm.movement = dir;
+ } else { // Reached the end or moving on the safe zone
+ if (pm.movement != -1) { // Reached the end
+ update_zones();
+ try_capture_zones();
+ update_progress();
+ pm.movement = -1;
+ }
+ }
+
+ is_view_update = 0;
+
+ return true;
}
-int movePacMan(int direction, int auto_call) {
-
- if(!canPacManMove(direction)) return 0;
-
- if(!auto_call && pm.movement != -1) {
-
- if(reverseDirection(pm.movement) != direction) pm.movement = direction;
-
- return 0;
-
- }
-
- nextLocation(&pm.location, direction);
-
- if(bricks[pm.location.x][pm.location.y] != -1) { //stepped out of the safe zone, run!
-
- bricks[pm.location.x][pm.location.y] = -2;
-
- pm.movement = direction;
-
- } else { //reached the end or moving on the safe zone
-
- if(pm.movement != -1) { //reached the end
-
- updateZones();
- tryCaptureZones();
- updateProgress();
- pm.movement = -1;
-
- }
-
- }
-
- view_validation = 0;
-
- return 1;
-
+void control_auto_moves() {
+ move_ghosts();
+
+ if (pm.movement != -1) move_pac_man(pm.movement, 1);
}
-int arrowToDirection(char a) {
-
- switch(a) {
-
- case UAKCC : return VERTICAL | UP;
- case DAKCC : return VERTICAL | !UP;
- case LAKCC : return HORIZONTAL | LEFT;
- case RAKCC : return HORIZONTAL | !LEFT;
-
- }
-
- return SHOULD_NOT_REACH_HERE;
-
+int arrow_to_dir(const int arrow_key_code) {
+ switch (arrow_key_code) {
+ case UP_AKC :
+ return VERTICAL | UP;
+ case DOWN_AKC :
+ return VERTICAL | !UP;
+ case LEFT_AKC :
+ return HORIZONTAL | LEFT;
+ case RIGHT_AKC :
+ return HORIZONTAL | !LEFT;
+ default:
+ return SHOULD_NOT_REACH_HERE;
+ }
}
-int main(){
-
- srand(time(NULL)); //for absolute random
- system("chcp 437"); //support ascii characters
- cls(); //clear Active Code Page : 437
-
- init();
-
- drawGame();
-
- while(1) {
-
- if(_kbhit()) {
-
- char c = _getch();
-
- switch(c) { //key press handler
-
- case AKCCM : { //arrow key
-
- movePacMan(arrowToDirection(_getch()), 0);
-
- break;
- }
-
- case SKCC : {
-
- bricks[pm.location.x][pm.location.y] = 0;
- updateZones();
- tryCaptureZones();
-
- }
-
- //default : printf("%d\t", c);
-
- }
-
- }
-
- purgePressedKeys();
- controlAutoMoves();
- drawGame();
- Sleep(1000/REFRESH_RATE);
- }
-
- return 0;
-
-}
+int main() {
+ initscr();
+ noecho();
+ nl();
+ keypad(stdscr, TRUE);
+ cbreak();
+ nodelay(stdscr, TRUE);
+
+ srand(time(NULL)); //for absolute random
+
+ clear_screen();
+ init();
+ draw_game();
+
+ while (true) {
+
+ if (kbhit()) {
+ int c = getch();
+ switch (c) { // Key press handler
+ case LEFT_AKC:
+ case RIGHT_AKC:
+ case UP_AKC:
+ case DOWN_AKC : { // Arrow key
+ move_pac_man(arrow_to_dir(c), 0);
+ break;
+ }
+ }
+ }
+
+ purge_keys();
+ control_auto_moves();
+ draw_game();
+ sleep_ms(1000 / REFRESH_RATE);
+ }
+
+ endwin();
+ return 0;
+}
\ No newline at end of file
diff --git a/pacman.c b/pacman.c
new file mode 100755
index 0000000..980521f
--- /dev/null
+++ b/pacman.c
@@ -0,0 +1,13 @@
+#ifndef PACMAN_C_INCLUDED
+#define PACMAN_C_INCLUDED
+
+#define PAC_MAN_CHAR "O"
+#define PAC_MAN_TRACE_CHAR "░"
+
+typedef struct {
+ loc_t location;
+ int movement;
+ int lives;
+} pac_man;
+
+#endif // PACMAN_C_INCLUDED
diff --git a/pacman.h b/pacman.h
deleted file mode 100755
index 0a139d0..0000000
--- a/pacman.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef PACMAN_H_INCLUDED
-#define PACMAN_H_INCLUDED
-
-#include "utils.h"
-
-#define PAC_MAN_CHAR 'O'
-#define PAC_MAN_TRACE_CHAR 176
-
-typedef struct {
-
- Location location;
- int movement;
- int lives;
-
-} PacMan;
-
-#endif // PACMAN_H_INCLUDED
diff --git a/utils.c b/utils.c
index f20c485..ce44089 100755
--- a/utils.c
+++ b/utils.c
@@ -1,436 +1,160 @@
-#include "utils.h"
+#ifndef UTILS_C_INCLUDED
+#define UTILS_C_INCLUDED
-#include
-#include
+#ifdef WINDOWS
#include
+#define SLEEP_MS(x) Sleep(x)
+#else
+#include
+#define SLEEP_MS(x) usleep((x) * 1000)
+#endif
-int randFlag() {
-
- return rand()%2;
-
-}
-
-void randPoint(Location * p, int minx, int maxx, int miny, int maxy) {
-
- p->x = minx + rand() % (maxx - minx + 1);
- p->y = miny + rand() % (maxy - miny + 1);
-
-}
-
-void print2DCharArray(int rows, int columns, char c[rows][columns]) {
-
- int i;
- for(i = 0; i < rows; i++) {
-
- int j;
- for(j = 0; j < columns; j++) {
-
- printf("%c", c[i][j]);
-
- }
-
- printf("\n");
-
- }
-
-}
-
-void printIntArray(int length, int array[length]) {
-
- int i;
- for(i = 0; i < length; i++) {
-
- printf("%d", array[i]);
-
- if(i != length - 1) printf(", ");
-
- }
-
-}
-
-void printDirectionsArray(int length, int directions[length]) {
-
- int i;
- for(i = 0; i < length; i++) {
-
- printDirection(directions[i]);
-
- if(i != length - 1) printf(", ");
-
- }
-
-}
-
-void printDirection(int direction) {
-
- int vertical_printed = 0;
-
- if(direction & VERTICAL) {
-
- if(direction & UP) printf("Up");
- else printf("Down");
-
- vertical_printed = 1;
-
- }
-
- if(direction & HORIZONTAL) {
-
- if(direction & LEFT) {
-
- if(vertical_printed) printf(" Left");
- else printf("Left");
-
- } else {
-
- if(vertical_printed) printf(" Right");
- else printf("Right");
-
- }
-
- }
-
-
-}
-
-int Replace2DintArray(int rows, int columns, int array[rows][columns], int key, int replace) {
-
- int replaceds = 0;
-
- int i;
- for(i = 0; i < rows; i++) {
-
- int j;
- for(j = 0; j < columns; j++) {
-
- if(array[i][j] == key) {
-
- array[i][j] = replace;
- replaceds++;
-
- }
-
- }
-
- }
-
- return replaceds;
-
-}
-
-int linearIntArraySearch(const int N, int array[N], int key) {
-
- int i;
- for(i = 0; i < N; i++) {
-
- if(array[i] == key) return i;
-
- }
-
- return -1;
-
-}
-
-void cls() {
-
- system("cls");
-
-}
-
-void nextLocation(Location * next, int direction) {
-
- if(direction & VERTICAL) {
-
- if(direction & UP) { //up
-
- next->x--;
-
- } else { //down
-
- next->x++;
-
- }
-
- }
-
- if(direction & HORIZONTAL) {
-
- if(direction & LEFT) { //left
-
- next->y--;
-
- } else { //right
-
- next->y++;
-
- }
-
- }
-
-}
-
-int reverseDirection(int direction) {
-
- if(direction & HORIZONTAL) direction ^= LEFT;
-
- if(direction & VERTICAL) direction ^= UP;
-
- return direction;
-
-}
-
-int randDirection(int diagonal) {
-
- if(diagonal) {
-
- return VERTICAL | HORIZONTAL | (randFlag() ? LEFT : !LEFT) | (randFlag() ? UP : !UP);
-
- } else {
-
- int rnd = rand()%4;
-
- return rnd == 0 ? (HORIZONTAL | LEFT) : rnd == 1 ? (VERTICAL | UP) : rnd == 2 ? (HORIZONTAL | !LEFT) : rnd == 3 ? (VERTICAL | !UP) : SHOULD_NOT_REACH_HERE;
-
-
- }
-
-}
-
-void purgePressedKeys() {
-
- while(_kbhit()) _getch();
-
-}
-
-int areNeighborPoints(Location p1, Location p2) {
-
- if(areEqualPoints(p1, p2)) return 0;
-
- int i;
- for(i = 0; i < 8; i++) {
-
- Location temp = p2;
-
- nextLocation(&temp, directions[i]);
-
- if(areEqualPoints(p1, temp)) return 1;
-
- }
-
- return 0;
-
-}
-
-int areEqualPoints(Location p1, Location p2) {
-
- return p1.x == p2.x && p1.y == p2.y;
-
-}
-
-void printPointArray(int length, Location p[length]) {
-
- int i;
- for(i = 0; i < length; i++) {
-
- printf("(%d, %d) ", p[i].x, p[i].y);
-
- }
-
-}
-
-void pVector(Location p1, Location p2, Location * result) {
-
- result->x = p2.x - p1.x;
- result->y = p2.y - p1.y;
-
-}
-
-int vectorToDirection(Location vector) {
-
- if(vector.x < 0 && vector.y < 0) { //up left
-
- return VERTICAL | HORIZONTAL | LEFT | UP;
-
- } else if(vector.x < 0 && vector.y == 0) { //up
-
- return VERTICAL | UP;
-
- } else if(vector.x < 0 && vector.y > 0) { //up right
-
- return VERTICAL | HORIZONTAL | !LEFT | UP;
-
- } else if(vector.x == 0 && vector.y < 0) { //left
-
- return HORIZONTAL | LEFT;
-
- } else if(vector.x == 0 && vector.y == 0) { //zero vector
-
- return SHOULD_NOT_REACH_HERE;
-
- } else if(vector.x == 0 && vector.y > 0) { //right
-
- return HORIZONTAL | !LEFT;
-
- } else if(vector.x > 0 && vector.y < 0) { //down left
-
- return HORIZONTAL | VERTICAL | !UP | LEFT;
-
- } else if(vector.x > 0 && vector.y == 0) { //down
-
- return VERTICAL | !UP;
-
- } else if(vector.x > 0 && vector.y > 0) { //down right
-
- return VERTICAL | HORIZONTAL | !UP | !LEFT;
-
- }
-
-}
-
-int areSideBySideLocations(Location l1, Location l2, int check_being_neighbors) {
-
- if(check_being_neighbors && !areNeighborPoints(l1, l2)) return 0;
-
- Location vector;
-
- pVector(l1 ,l2, &vector);
-
- int sbs = vectorToDirection(vector);
-
- if(sbs & VERTICAL && sbs & HORIZONTAL) return 0;
- else return 1;
-
-}
-
-void printPoint(Location p) {
-
- printf("(%d, %d)", p.x, p.y);
-
-}
-
-int reflectDirection(int direction, int mirror_position) {
-
- ///
-
-}
-
-int findCommonElementsOfIntArrays(int result_length, int array1_length, int array2_length, int result[result_length], int array1[array1_length], int array2[array2_length]) {
-
- int rai = 0; //result append index
- int has_space = result_length != 0;
-
- //set the smaller length array as base
-
- if(array1_length < array2_length) {
-
- int i;
- for(i = 0; i < array1_length; i++) {
-
- if(linearIntArraySearch(array2_length, array2, array1[i]) != -1) { //found a common int
-
- if(has_space) result[rai] = array1[i];
-
- rai++;
-
- if(rai == result_length) has_space = 0;
-
- }
-
- }
-
- } else {
-
- int i;
- for(i = 0; i < array2_length; i++) {
-
- if(linearIntArraySearch(array1_length, array1, array2[i]) != -1) { //found a common int
-
- if(has_space) result[rai] = array2[i];
-
- rai++;
-
- if(rai == result_length) has_space = 0;
-
- }
-
- }
-
- }
-
- return rai;
-
-}
-
-void insertionSortIntArray(int length, int array[length]) {
-
- int i;
- for(i = 1; i < length; i++) {
-
- int j;
- for(j = i; array[j] < array[j-1] && j > 0; j--) {
-
- int t = array[j];
- array[j] = array[j-1];
- array[j-1] = t;
-
- }
-
- }
-
-}
-
-int shiftLeftIntArray(int N, int array[N], int remove_index) {
-
- if(remove_index < 0) return 0;
- if(remove_index == N - 1) return 1;
-
- int executed = 0;
-
- int i;
- for(i = remove_index + 1; i < N; i++) {
-
- int t = array[i];
- array[i] = array[i-1];
- array[i-1] = t;
-
- if(!executed) executed = 1;
-
- }
-
- return executed;
-
-}
-
-void bugAlert(char * msg) {
-
- printf("Bug : %s", msg);
- Sleep(1000);
-
-}
-
-int turnDirection(int direction, int clockwise, int steps) {
-
- //find its index at directions
- int index;
- if((index = linearIntArraySearch(8, directions, direction)) == -1) return SHOULD_NOT_REACH_HERE; //not a direction
-
- int i;
- for(i = 0; i < steps; i++) {
-
- if(clockwise) {
-
- direction = directions[index == 7 ? 0 : index + 1];
-
- } else {
-
- direction = directions[index == 0 ? 7 : index - 1];
-
- }
-
- }
-
- return direction;
-
-}
-
-
+#include
+#include
+#include
+#include "kbhit.c"
+
+// AKC = Arrow Key Code
+#define LEFT_AKC KEY_LEFT
+#define RIGHT_AKC KEY_RIGHT
+#define UP_AKC KEY_UP
+#define DOWN_AKC KEY_DOWN
+
+#define SHOULD_NOT_REACH_HERE (-1)
+
+bool rand_bool() {
+ return rand() % 2;
+}
+
+void print_2d_str_arr(const int rows, const int columns, const char *arr[rows][columns]) {
+ int i;
+ for (i = 0; i < rows; i++) {
+ int j;
+ for (j = 0; j < columns; j++) {
+ printf("%s", arr[i][j]);
+ }
+ printf("\r\n");
+ }
+}
+
+void print_int_arr(const int size, const int arr[size]) {
+ int i;
+ for (i = 0; i < size; i++) {
+ printf("%d", arr[i]);
+ if (i != size - 1) printf(", ");
+ }
+}
+
+int replace_2d_int_arr(const int rows, const int columns, int arr[rows][columns], const int key, const int replace) {
+ int replaceds = 0;
+
+ int i;
+ for (i = 0; i < rows; i++) {
+ int j;
+ for (j = 0; j < columns; j++) {
+ if (arr[i][j] == key) {
+ arr[i][j] = replace;
+ replaceds++;
+ }
+ }
+ }
+
+ return replaceds;
+}
+
+int linear_int_arr_search(const int size, const int arr[size], const int key) {
+ int i;
+ for (i = 0; i < size; i++) {
+ if (arr[i] == key) return i;
+ }
+
+ return -1;
+}
+
+void clear_screen() {
+#ifdef WINDOWS
+ system("cls");
+#else
+ system("clear");
+#endif
+}
+
+void purge_keys() {
+ while (kbhit()) getch();
+}
+
+int find_common_elements_of_int_arrs(
+ const int res_size, const int arr1_size, const int arr2_size, int res[res_size],
+ const int arr1[arr1_size], const int arr2[arr2_size]
+) {
+
+ int rai = 0; // Result Append Index
+ bool has_space = res_size != 0;
+
+ // Set the smaller length array as base
+ if (arr1_size < arr2_size) {
+ int i;
+ for (i = 0; i < arr1_size; i++) {
+ if (linear_int_arr_search(arr2_size, arr2, arr1[i]) != -1) { // Found a common int
+ if (has_space) res[rai] = arr1[i];
+ rai++;
+
+ if (rai == res_size) has_space = false;
+ }
+ }
+ } else {
+ int i;
+ for (i = 0; i < arr2_size; i++) {
+ if (linear_int_arr_search(arr1_size, arr1, arr2[i]) != -1) { // Found a common int
+ if (has_space) res[rai] = arr2[i];
+ rai++;
+
+ if (rai == res_size) has_space = false;
+ }
+ }
+ }
+
+ return rai;
+}
+
+void insertion_sort_int_arr(int size, int arr[size]) {
+ int i;
+ for (i = 1; i < size; i++) {
+ int j;
+ for (j = i; arr[j] < arr[j - 1] && j > 0; j--) {
+ const int t = arr[j];
+ arr[j] = arr[j - 1];
+ arr[j - 1] = t;
+ }
+ }
+}
+
+bool shift_left_int_arr(const int size, int arr[size], const int remove_index) {
+
+ if (remove_index < 0 || remove_index >= size) return false;
+ else if (remove_index == size - 1) return true;
+
+ bool executed = false;
+
+ int i;
+ for (i = remove_index + 1; i < size; i++) {
+ const int t = arr[i];
+ arr[i] = arr[i - 1];
+ arr[i - 1] = t;
+
+ if (!executed) executed = true;
+ }
+
+ return executed;
+}
+
+void sleep_ms(const long ms) {
+ SLEEP_MS(ms);
+}
+
+void bug_alert(const char *msg) {
+ printf("Bug: %s", msg);
+ sleep_ms(1000);
+}
+
+#endif // UTILS_C_INCLUDED
\ No newline at end of file
diff --git a/utils.h b/utils.h
deleted file mode 100755
index eb0e53b..0000000
--- a/utils.h
+++ /dev/null
@@ -1,98 +0,0 @@
-#ifndef UTILS_H_INCLUDED
-#define UTILS_H_INCLUDED
-
-#include
-#include
-#include
-
-//directions
-#define VERTICAL 0b0001
-#define HORIZONTAL 0b0010
-#define LEFT 0b0100
-#define UP 0b1000
-
-//Key Char Codes = KCC
-#define AKCCM -32 //Arrow Key Char Code Modifier
-#define LAKCC 75 //Left Arrow Key Char Code
-#define RAKCC 77 //Right Arrow Key Char Code
-#define UAKCC 72 //Up Arrow Key Char Code
-#define DAKCC 80 //Down Arrow Key Char Code
-#define SKCC 32 //Enter Key Char Code
-
-//something
-#define SHOULD_NOT_REACH_HERE -1
-
-#define PERCENT_CHAR 37 //percent character
-
-//point = location; x = row, y = column
-typedef struct {
-
- int x, y;
-
-} Location;
-
-//clockwise order
-static int directions[8] = {VERTICAL | UP, //up
- HORIZONTAL | VERTICAL | UP | !LEFT, //up right
- HORIZONTAL | !LEFT, //right
- HORIZONTAL | VERTICAL | !UP | !LEFT, //down right
- VERTICAL | !UP, //down
- HORIZONTAL | VERTICAL | !UP | LEFT, //down left
- HORIZONTAL | LEFT, //left
- HORIZONTAL | VERTICAL | UP | LEFT}; //up left
-
-//random boolean
-int randFlag();
-
-//fills the passed point with random x, y within inclusive specified bounds
-void randPoint(Location * p, int minx, int maxx, int miny, int maxy);
-
-//prints the 2D char array
-void print2DCharArray(int rows, int columns, char c[rows][columns]);
-
-//clear dos
-void cls();
-
-//next step of the move by the specified direction
-//next : current location; will be replaced by the new location
-void nextLocation(Location * next, int movement);
-
-int randDirection(int diagonal);
-
-void printIntArray(int length, int a[length]);
-
-void printPointArray(int length, Location p[length]);
-
-void printPoint(Location p);
-
-void pVector(Location p1, Location p2, Location * result);
-
-int areEqualPoints(Location p1, Location p2);
-
-int areNeighborPoints(Location p1, Location p2);
-
-int reverseDirection(int direction);
-
-void printIntArray(int length, int array[length]);
-
-void printDirection(int direction);
-
-int linearIntArraySearch(const int N, int array[N], int key);
-
-int Replace2DintArray(int rows, int columns, int array[rows][columns], int key, int replace);
-
-void insertionSortIntArray(int length, int array[length]);
-
-//returns founded elements count; result array filled length
-int findCommonElementsOfIntArrays(int result_length, int array1_length, int array2_length, int result[result_length], int array1[array1_length], int array2[array2_length]);
-
-//returns the shift execution
-int shiftLeftIntArray(int N, int array[N], int remove_index);
-
-void bugAlert(char * msg);
-
-int areSideBySideLocations(Location l1, Location l2, int check_being_neighbors);
-
-int turnDirection(int direction, int clockwise, int steps);
-
-#endif // UTILS_H_INCLUDED