diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..f49a4e1
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/PacXon.cbp b/PacXon.cbp
new file mode 100755
index 0000000..87d0603
--- /dev/null
+++ b/PacXon.cbp
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1c85dc8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,13 @@
+# PacXon
+
+A partial PacXon game clone in C & Windows cmd.exe (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**.
+
+![A Screenshot](./Screenshot.png)
+
+## Simple build & run
+
+Open the project in Code::Blocks 17.12 (with MinGW) on a Windows OS, and hit Build and run.
+
+> Running the game might be tricky; because it is a legacy software now, and it was not packaged professionally.
\ No newline at end of file
diff --git a/Screenshot.png b/Screenshot.png
new file mode 100644
index 0000000..6f64774
Binary files /dev/null and b/Screenshot.png differ
diff --git a/ghosts.c b/ghosts.c
new file mode 100755
index 0000000..075fd70
--- /dev/null
+++ b/ghosts.c
@@ -0,0 +1 @@
+#include "ghosts.h"
diff --git a/ghosts.h b/ghosts.h
new file mode 100755
index 0000000..5e8116b
--- /dev/null
+++ b/ghosts.h
@@ -0,0 +1,32 @@
+#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/main.c b/main.c
new file mode 100755
index 0000000..df956e7
--- /dev/null
+++ b/main.c
@@ -0,0 +1,1017 @@
+/**
+to dos :
+ - brick zone ghost creation : appears after 5%
+ - brick zone ghost move algorithm
+ - power ups
+ - progress != 100% bug
+ - score
+ - collisions...
+ - restart
+ - save and load
+ - levels
+ - menu
+ - reflectDirection method
+ - colored char struct
+**/
+
+#include
+#include
+#include
+#include "utils.h"
+#include "ghosts.h"
+#include "pacman.h"
+
+#define MAX_GHOSTS 100 //maximum capacity of the ghosts array
+
+#define REFRESH_RATE 120 //Hz; affects velocity of things in game (pac man, ghosts)
+
+//shapes
+#define BRICK_CHAR 178
+
+//the whole game boar dimensions
+#define ROWS 30
+#define COLUMNS 70
+
+#define WIN_PROGRESS 80 //win condition
+
+//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
+
+//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() {
+
+ int append_index = 0;
+
+ int i;
+ for(i = 0; i < float_ghosts; i++) { //float ghosts
+
+ addGhost(FLOAT_GHOST, append_index);
+ append_index++;
+
+ }
+
+ 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++;
+
+ }
+
+}
+
+//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++;
+
+}
+
+//how pac man starts
+void initPacMan() {
+
+ pm.location.x = 0;
+ pm.location.y = 0;
+
+ pm.movement = -1;
+ pm.lives = 3;
+
+}
+
+//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
+
+ }
+
+ }
+
+}
+
+//draws whole things
+void drawGame() {
+
+ if(view_validation) return;
+
+ updatePicture();
+
+ cls();
+
+ //print the header
+ drawHeader();
+
+ //print the picture
+ print2DCharArray(ROWS, COLUMNS, picture);
+
+}
+
+void init() {
+
+ ghosts_quantity = float_ghosts + rail_ghosts + brick_zone_ghosts;
+
+ initBricks();
+ initGhosts();
+ initPacMan();
+
+}
+
+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 drawHeader() {
+
+ printf("Lives: %d\tScore: %d\tProgress: %d/%d%c\n", pm.lives, score, progress, WIN_PROGRESS, PERCENT_CHAR);
+
+}
+
+void controlAutoMoves() {
+
+ moveGhosts();
+
+ if(pm.movement != -1) movePacMan(pm.movement, 1);
+
+}
+
+//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 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;
+ }
+
+ }
+
+}
+
+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;
+
+}
+
+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 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 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 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;
+
+}
+
+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;
+
+}
+
+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 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;
+
+}
diff --git a/pacman.h b/pacman.h
new file mode 100755
index 0000000..0a139d0
--- /dev/null
+++ b/pacman.h
@@ -0,0 +1,17 @@
+#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
new file mode 100755
index 0000000..f20c485
--- /dev/null
+++ b/utils.c
@@ -0,0 +1,436 @@
+#include "utils.h"
+
+#include
+#include
+#include
+
+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;
+
+}
+
+
diff --git a/utils.h b/utils.h
new file mode 100755
index 0000000..eb0e53b
--- /dev/null
+++ b/utils.h
@@ -0,0 +1,98 @@
+#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